[express] firebase auth 소셜 로그인 기능 서버 구현 (Typescript)

하람·2024년 10월 24일

Express 서버

목록 보기
7/7

앱스토어 출시까지 고려하고 있기 때문에, firebase를 이용해 소셜 로그인을 구현해서 보안과 개발편의성 두마리 토끼를 다 잡을 생각이다 ^^

Firebase Authentication

  • 앱에서 사용자 인증 시 필요한 백엔드 서비스와 사용하기 쉬운 SDK, 기성 UI 라이브러리를 제공
  • 비밀번호, 전화번호, 인기 제휴 ID 공급업체(예: Google, Facebook, Twitter 등)를 통해 인증

구현 흐름

React Native 클라이언트에서 Firebase Auth API를 사용하여 사용자를 인증하고, 백엔드(Express + Firebase Admin SDK)에서 해당 토큰을 검증하는 방식!

  • 회원가입: 클라이언트에서 Firebase를 사용하여 사용자를 생성하고, ID 토큰을 발급받아 서버로 전송.
  • 로그인: Firebase에서 사용자 인증을 처리하고, 클라이언트에서 서버로 토큰을 전송하여 인증을 유지.
  • 백엔드 서버는 Firebase의 Admin SDK를 사용해 ID 토큰을 검증하여 사용자의 로그인 상태를 확인 및 유지.

서버가 할 일은 무엇인가?

  • 회원가입
    • 토큰 확인하고 (이미 가입되진 않았는지)
    • DB에 사용자 생성 후 사용자 id 저장
  • 로그인:
    • 토큰 확인하고 (가입된 유저 맞는지)
    • 디바이스토큰 변했다면 다시저장
  • 토큰인증(미들웨어):
    • 토큰인증 메소드 제공
  • 로그아웃: 프론트에서 끝

Firebase admin SDK 초기화

// Firebase Admin SDK 초기화
const serviceAccount = require('../path-to-your-service-account-key.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

auth 토큰 인증 미들웨어

// 미들웨어: Firebase 토큰을 검증하는 함수
const verifyFirebaseToken = async (req: any, res: any, next: any) => {
  const idToken = req.headers.authorization?.split('Bearer ')[1];

  if (!idToken) {
    return res.status(401).send('Authorization token missing');
  }

  try {
    const decodedToken = await admin.auth().verifyIdToken(idToken);
    req.user = decodedToken;
    next();
  } catch (error) {
    res.status(401).send('Unauthorized');
  }
};

회원가입

app.post('/signup', verifyFirebaseToken, (req: Request, res: Response) => {
  const user = req.user; // Firebase에서 인증된 사용자 정보
  // 추가로 회원 정보 저장을 원한다면 DB에 사용자 정보 저장 등의 작업 수행 가능
  res.status(201).json({ message: 'User signed up successfully', user });
});

로그인

app.post('/login', verifyFirebaseToken, (req: Request, res: Response) => {
  const user = req.user; // Firebase에서 인증된 사용자 정보
  res.status(200).json({ message: 'User logged in successfully', user });
});

Extend Express Request object using Typescript

auth middleware에서 Request 에 유저 정보를 담아주고자 하기 때문에, 타입을 확장시켜야한다.

Extend Type

// /src/types/express/index.d.ts
import { User } from "firebase/auth";

declare global {
  namespace Express {
    interface Request {
      user?: User;
    }
  }
}

update tsconfig.json

{
  "compilerOptions": {
    // ...
    "typeRoots": ["./src/types", "./node_modules/@types"]
  },
profile
강하고 담대하라 두려워하지 말라

0개의 댓글