[React Native] Firebase Authentication Token with Expo app

Jaehyun Park·2024년 4월 1일
0

기존 CLIP 앱은 Firebase Auth를 통해 생성된 UID를 UserContext에 넣어 전역에서 사용하도록 했고, 보안 관련 문제는 전혀 다루지 않았다.

이번 프로젝트에서는 Firebase Auth 기능을 제대로 사용하여 보안 관련 기능을 구축하고자 한다.


1. 개념 설계

  1. 사용자가 Expo App을 실행한다.

  2. App이 실행되면 Expo CLI(Metro Bundler)에 의해 exp://xxx.xx.x.xxx:8081metro server가 실행된다. local IP는 달라지며, Port는 8081이다.

  3. 사용자가 이메일과 비밀번호를 입력하여 로그인을 시도한다.

  4. 클라이언트(expo app)에서 Firebase SDK를 통해 Firebase Auth API에 인증을 요청한다. 이때 통신 프로토콜은 HTTP:POST이다.

  5. Firebase Auth에서 클라이언트로부터 받은 Email과 Password로 유효한 유저 정보인지 확인하여 유효성 입증한다. 유효성이 입증되면 데이터가 Firebase Authentication만의 암호화 알고리즘에 의해 인코딩되고, 이 값을 '인증 토큰'으로 클라이언트에 전달한다. Firebase는 인증 토큰을 ID Token이라 칭하고 있다. 토큰 타입은 JWT다.

    1) Authentication(인증)
    로그인, 회원가입한 사용자에 대하여 유효한 사용자인지 확인하고 콘텐츠에 대한 접근 권한을 설정하는 절차이다. MyPage는 로그인한 사용자만 이용하게 하거나, 비밀번호 변경 요청 등이 그 예시이다. 서버 측에서는 클라이언트에게 받은 요청에 대해 이 요청이 인증받은 사용자의 요청인지 검사한 후, 인증받은 사용자만 요청에 대한 응답을 클라이언트에 전달하도록 동작해야 한다.

    2) Authentication Token(인증 토큰)
    사용자 인증을 위해 사용되는 수단 중의 하나로, 서버만이 알고 있는 secret key로 특정 암호화 알고리즘을 사용하여 데이터를 암호화된 문자열로 인코딩한 것이다. 생성된 인증 토큰은 서버에 저장되지 않고 클라이언트에 전달되며, 이 인증 토큰은 클라이언트가 서버에 어떠한 요청을 할 때마다 함께 첨부하여 이 요청이 유효한 유저의 요청인지 확인할 수 있게 된다.
    서버에서 인증 토큰을 복호화(암호화의 반대) 하고 유효한 인증 토큰인지 검사하기 위해 payload라고 하는 필드에 UID 같은 유저 식별자가 들어가있어야 한다. 인증토큰은 대부분 만료 시간이 있어 주기적으로 발급 받아야 하는 것이 특징이다.

    3) JWT(JSON Web Token)
    인증 토큰의 종류는 여러가지가 있는데, 그 중에 가장 일반적으로 사용되는 인증 토큰 방식이다.
    각 필드는 .로 구분되며, Header, Payload, Signature 총 3가지 필드로 구성된다. 각 필드는 모두 base64 방식으로로 인코딩된다.

    1) Header
    JWT의 암호값인 서명(verify signature) 필드의 값을 만드는데 사용되는 alg(알고리즘)typ(토큰 타입)으로 구성된다. 여기서 타입은 JWT 고정이다.


    2) Payload
    JWT의 내용을 담은 부분으로, payload에 들어갈 정보들은 claim이라 부른다. claim등록된 클레임(registered claims), 공개 클레임-사용자 설정 클레임(public claims), 비공개 클레임(private claims)이 있다. 등록된 클레임에는 iss(데이터 발행자), iat(데이터 발생 시간), exp(데이터 만료 시간), sub(토큰 제목) 등이 서버에서 디코딩 했을 때 확인할 수 있는 정보들이 담겨있다.


    3. Verify Signature
    서버가 클라이언트의 인증 상태 유효성을 입증할 때 사용되는 부분이다. (base64UrlEncode(header) + . + base64UrlEncode(payload), secret key) 구성으로 Header에 정의된 알고리즘으로 인코딩하여 암호화한 값이다. 클라이언트가 요청과 함께 JWT를 전달하면 서버는 전달받은 JWT의 Verify Signature 필드값을 자신이 갖고 있는 키 값으로 복호화 하여 HeaderPayload 필드 내용을 확인할 수 있다. Payload 필드의 사용자 고유 ID나 인증 토큰 만료 시간 등의 정보를 통해 유효성 검사가 가능하다.

  6. Firebase Authentication API로부터 인증 토큰(ID Token)을 받았다면, 클라이언트는 이제부터 서버에 요청을 보낼 때 인증 토큰을 첨부하여 서버에 요청을 날린다. 인증 토큰을 받은 서버는 secret key를 통해 인증 토큰을 디코딩(복호화)하여 인증 토큰의 유효성 검사를 실시한다. 이때 서버는 복호화된 JWT의 Header, Payload 필드 내용을 확인하고 인가(Authorization) 여부를 결정한다. 클라이언트가 보낸 인증 토큰이 유효하여 인가되었다면 Endpoint API통해 해당 클라이언트의 요청 및 응답의 권한(permission)이 수락된다.

    1) Authorization(인가)
    클라이언트가 요청을 실행할 수 있는 권한이 있는 클라이언트인인지 확인하는 절차이다.
    JWT를 사용하면 서버가 DB에 유저 정보를 갖고 있으므로 DB에서 해당 유저의 권한 정보도 읽어들이면 되고, 인증 토큰을 통해 해당 유저 정보를 얻을 수 있으므로 해당 유저가 갖고 있는 권한(permission)도 확인 가능하다. 인가된 유저는 서버로 요청하면 비로소 응답을 받을 수 있다.

    2) Server Side Unencrypt
    유저가 request를 보낼 때 같이 보낸 인증토큰을 서버에서 복호화하고, 복호화된 데이터를 통해 유저 식별자 획득한다. 이 식별자를 통해 데이터베이스에서 해당 유저의 권한을 확인하게 된다. 유저가 충분한 권한을 갖고 있으면 해당 요청을 처리하고, 권한을 갖고 있지 않으면 Unauthorized Response(401) 또는 다른 에러 코드 전송하면 된다.

  7. 사용자 JWT가 인가되어도 요청을 보낼 때마다 항상 JWT를 첨부하여 보내야 하므로, Expo-secure-store에 해당 토큰을 저장하여 캐싱하고, 권한이 필요한 요청이 발생할 때마다 꺼내어 유저 로그인 정보를 유지할 수 있다.


2. 해결해야 할 것

  1. 데이터베이스에 비밀번호 저장 여부: firebase auth를 사용하는데 필요가 있을까? 검토 필요

  2. spring에 spring secure라는 라이브러리가 있는데, 이걸로 JWT 인가 가능하다고 함

  3. 처음부터 Firebase Auth Custom Token 사용하는 방법도 검토

profile
Technologically solve everyday challenges

0개의 댓글