Firebase Authentication
Authentication(인증)?
앱, 웹에 모든 사용자가 모든 컨텐츠에 접근할 수 있어야 하는것은 아니다. 이런 접근에 대한 권한을 "인증(Authentication)"을 통해 보호할 수 있다. 페이지 뿐만 아닌 데이터베이스에 저장된 데이터, 앱의 기능들을 인증을 통해 권한을 제어하고 데이터를 보호할 수 있다.
인증이 된 사용자만이 어떤 기능을 이용할 수 있고, 사용자 인증을 통해 데이터를 조작할 수 있게끔 한다던지..
즉, 서버는 클라이언트에게 전달받은 요청에 따라서 인증 받은 사용자인지 검사를 하고, 인증받은 사용자에게만 요청에 대한 응답을 클라이언트에게 전달할 수 있어야 한다.
이런 인증의 방법으로는 "로그인"이 있다. 로그인을 위한 버튼을 누르면 정보가 서버로 전달되고, 서버는 연결된 데이터베이스에 전달된 정보를 확인하고 사용자 유효성이 입증되면 인증을 응답으로 제공한다.
Authentication을 이해하기 위해선 HTTP통신과 Session과 Cookie에 대해 간략한 이해가 있으면 좋다.
https://clamp-coding.tistory.com/460
- 페이스북, 구글, 트위터, 깃헙등 계정의 권한을 위힘하는 과정으로, 위임받아 인증 key(Access Token)를 보관하는 서버를 쉽게 구현할 수 있다.
- 로그인 서버를 따로 두는 개념.
Authentication Token
계정과 비밀번호를 서버에 보내게 되면 서버가 데이터베이스에 저장된 이메일과 비밀번호를 비교해서 유효성을 인증한다. 유효성이 입증되면 서버가 인증토큰을 만들게 된다.
인증 토큰은 "아주 긴 문자열" 형태이며 데이터가 문자열로 인코딩 되어있다. 서버는 데이터를 인코딩할 때 특정 알고리즘(암호화 알고리즘)으로 서버만이 갖고있는 key를 사용하여 인증 토큰을 생성한다.
즉, 서버가 인증토큰을 만들 때 서버만 알고있는 key를 갖고 특정 알고리즘을 사용하여 데이터를 문자열로 인코딩하게 된다. 토큰을 만드는 과정에 포함되는 키는 서버만이 알고 있기 때문에 사용자는 토큰을 디코딩하거나 어떻게 생성되었는지 알 수 없다. 그리고 생성된 토큰은 서버에 저장되지 않고 단지 사용자에게 전달된다.
사용자는 서버에게 요청을 보낼 때 인증토큰도 함께 전달한다. 토큰을 받은 서버는 자신이 갖고있는 키를 이용하여 디코드하게 된다. 그리고 토큰이 유효한 경우에 리소스에 대한 접근을 허용하게 된다. 이는 앞선 Session 방식처럼 서버측에서 각 사용자마다 고유한 SessionID를 갖고있지 않아도 된다.
서버가 인증토큰을 응답으로 보냈다는 것은 사용자가 유효하다는 의미이다. 만약 유효하지 않은 사용자라면 서버측에서는 인증토큰을 전달해주지 않을 것이다. 따라서 우리는 서버가 응답한 인증토큰의 존재 유무를 사용자가 인증이 되었다라는 근거로 사용할 수 있다.
또한 OAuth방식을 사용하기 때문에 OAuth 2.0의 사전 지식이 필요하다.
https://clamp-coding.tistory.com/461
여기선 apple OAuth를 활용한 Rest API를 활용해본다.
- Http 요청 메서드: POST
- 요청 몸체의 Content-Type: application/json
- API의 URI의 API_KEY: 자신이 부여받은 웹API로 치환. 자신의 APIKEY는 프로젝트 설정에서 확인할 수 있다.
curl 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=[API_KEY]' \
-H 'Content-Type: application/json' \
--data-binary '{"postBody":"id_token=[APPLE_ID_TOKEN]&providerId=[apple.com]","requestUri":"[http://localhost]","returnIdpCredential":true,"returnSecureToken":true}'
위의 예에서 [API_KEY] 를 Firebase 프로젝트의 Web API 키로, [GOOGLE_ID_TOKEN]을 Google OAuth ID 토큰으로, [google.com]을 OAuth 자격 증명에 해당하는 공급자 ID로, [http://localhost]를 요청 URI와 함께 사용합니다.
우선 Request를 먼저 보자면..
여기서 "자격증명"이란 OAuth에서 Access Token을 포함한 인증 정보를 의미한다.
- requestUri: IDP는 Identiy Provider의 약자이다. 사용자를 인증하는 서비스이다. 사용자가 인증을 마치고 IDP로부터 리디렉션되는 주소를 나타낸다. 이 주소는 사용자가 인증 프로세스를 완료한 후 다시 돌아갈 위치를 지정하는 역할을 한다.
- postBody: OAuth인증에 사용되는 엑세스토큰을 나타낸다. 인증에 사용되는 자격증명과 해당 자경증명을 발급한 공급자 ID를 담고있어야 한다.
- returnSecureToken: ID와 리프레시 토큰을 반환할지 여부이다. 항상 true여야 한다.
- returnIdpCredential: FEDRATED_USER_ID_ALREADY_LINKED and EMAIL_EXISTS 오류가 발생할 경우 OAuth 자격증명을 강제로 반환할지 여부를 나타낸다.
api 호출을 해보면..
https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=[FIREBASE_API_KEY]&requestUri=https://devreels.firebaseapp.com/__/auth/handler&postBody=id_token=[APPLE에서 발급받은 token]
%26providerId=apple.com%26nonce=zBrCgZS4bjt1uURiizqDuDTEZ6clpHsA&returnIdpCredential=true&returnSecureToken=true
이정도가 될 것 같다.
apple login에는 추가적으로 postbody에 nonce라는게 필요하다. 이는 위에 링크걸어둔 OAuth를 공부해보면 알 수 있다.
만약 성공적으로 사용자 추가가 완료된다면 응답으로 위와 같은 객체를 전달받게 된다.
사용자 인증 상태 유지
+ 추가예정