Firebase 클라이언트 앱이 커스텀 백엔드 서버와 통신하는 경우 서버에 현재 로그인한 사용자를 식별해야 할 수 있습니다. 사용자를 안전하게 식별하려면 로그인이 정상적으로 이루어진 후에 HTTPS를 사용하여 사용자의 ID 토큰을 서버로 전송합니다. 그런 다음 서버에서 ID 토큰의 무결성과 진위를 검증하고 ID 토큰에서 uid
를 가져옵니다. 이 방법으로 전송된 uid
를 사용하면 현재 서버에 로그인한 사용자를 안전하게 식별할 수 있습니다.
시작하기 전에
Firebase Admin SDK로 ID 토큰을 검증하려면 서비스 계정이 있어야 합니다. 서비스 계정으로 Admin SDK를 초기화하는 자세한 방법은 Admin SDK 설정 안내를 참조하세요.
클라이언트에서 ID 토큰 검색
사용자 또는 기기가 로그인에 성공하면 Firebase는 이들을 고유하게 식별하는 해당 ID 토큰을 만들고 Firebase Realtime Database 및 Cloud Storage와 같은 여러 리소스에 대한 액세스를 허용합니다. 맞춤 백엔드 서버에서는 이 ID 토큰을 재사용하여 사용자 또는 기기를 식별할 수 있습니다. 클라이언트에서 ID 토큰을 검색하려면 다음과 같이 사용자가 로그인한 상태인지 확인하고 로그인한 사용자의 ID 토큰을 가져옵니다.
iOS+
Objective-C
FIRUser *currentUser = [FIRAuth auth].currentUser;
[currentUser getIDTokenForcingRefresh:YES
completion:^(NSString *_Nullable idToken,
NSError *_Nullable error) {
if (error) {
// Handle error
return;
}
// Send token to your backend via HTTPS
// ...
}];
Swift
let currentUser = FIRAuth.auth()?.currentUser
currentUser?.getIDTokenForcingRefresh(true) { idToken, error in
if let error = error {
// Handle error
return;
}
// Send token to your backend via HTTPS
// ...
}
Android
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
Unity
Firebase.Auth.FirebaseUser user = auth.CurrentUser;
user.TokenAsync(true).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("TokenAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("TokenAsync encountered an error: " + task.Exception);
return;
}
string idToken = task.Result;
// Send token to your backend via HTTPS
// ...
});
C++
firebase::auth::User user = auth->current_user();
if (user.is_valid()) {
firebase::Future<std::string> idToken = user.GetToken(true);
// Send token to your backend via HTTPS
// ...
}
웹
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
// Send token to your backend via HTTPS
// ...
}).catch(function(error) {
// Handle error
});
ID 토큰이 확보되었으면 이 JWT를 백엔드로 전송하여 Firebase Admin SDK로 검증할 수 있습니다. Firebase가 기본적으로 지원하지 않는 언어로 서버가 작성된 경우 서드 파티 JWT 라이브러리를 사용할 수도 있습니다.
Firebase Admin SDK로 ID 토큰 검증
Firebase Admin SDK에는 ID 토큰 검증 및 디코딩을 담당하는 메소드가 내장되어
있습니다. 제공된 ID 토큰이 올바른 형식이고, 만료되지 않았으며, 정상적으로 서명된 경우 이 메서드는 디코딩된 ID 토큰을 반환합니다. 디코딩된 토큰에서 사용자 또는 기기의 uid
를 확인할 수 있습니다.
Admin SDK 설정 안내에 따라 서비스 계정으로 Admin SDK를 초기화합니다. 그런 다음 verifyIdToken()
메서드를 사용하여 ID 토큰을 확인합니다.
Node.js
// idToken comes from the client app
getAuth()
.verifyIdToken(idToken)
.then((decodedToken) => {
const uid = decodedToken.uid;
// ...
})
.catch((error) => {
// Handle error
});
Java
// idToken comes from the client app (shown above)
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
String uid = decodedToken.getUid();
Python
# id_token comes from the client app (shown above)
decoded_token = auth.verify_id_token(id_token)
uid = decoded_token['uid']
Go
client, err := app.Auth(ctx)
if err != nil {
log.Fatalf("error getting Auth client: %v\n", err)
}
token, err := client.VerifyIDToken(ctx, idToken)
if err != nil {
log.Fatalf("error verifying ID token: %v\n", err)
}
log.Printf("Verified ID token: %v\n", token)
C#
FirebaseToken decodedToken = await FirebaseAuth.DefaultInstance
.VerifyIdTokenAsync(idToken);
string uid = decodedToken.Uid;
ID 토큰 확인을 위해서는 프로젝트 ID가 필요합니다. Firebase Admin SDK는 다음 방법 중 하나를 사용하여 프로젝트 ID를 가져오려고 시도합니다.
- SDK가 명시적인
projectId
앱 옵션을 사용해서 초기화된 경우 SDK가 해당 옵션의 값을 사용합니다. - SDK가 서비스 계정 사용자 인증 정보를 사용하여 초기화된 경우 SDK가 서비스 계정 JSON 객체의
project_id
필드를 사용합니다. GOOGLE_CLOUD_PROJECT
환경 변수가 설정된 경우 SDK는 해당 값을 프로젝트 ID로 사용합니다. 이 환경 변수는 App Engine 및 Compute Engine과 같은 Google 인프라에서 실행되는 코드에 사용할 수 있습니다.
타사 JWT 라이브러리로 ID 토큰 검증
백엔드가 Firebase Admin SDK에서 지원하지 않는 언어로 작성되었더라도 ID 토큰을 검증할 수 있습니다. 우선 해당 언어의 서드 파티 JWT 라이브러리를 검색합니다. 그런 다음 ID 토큰의 헤더, 페이로드 및 서명을 검증합니다.
ID 토큰의 헤더가 다음과 같은 제약조건에 맞는지 확인합니다.
ID 토큰 헤더 클레임 | ||
---|---|---|
alg |
알고리즘 | "RS256" |
kid |
키 ID |
https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com 에 나열된 공개 키 중 하나와 일치해야 합니다.
|
ID 토큰의 페이로드가 다음 제약조건에 맞는지 확인합니다.
ID 토큰 페이로드 클레임 | ||
---|---|---|
exp |
만료 시간 | 미래 시간이어야 합니다. UNIX 기점을 기준으로 측정한 시간(초)입니다. |
iat |
발급 시간 | 과거 시간이어야 합니다. UNIX 기점을 기준으로 측정한 시간(초)입니다. |
aud |
잠재고객 | Firebase 프로젝트 ID(Firebase 프로젝트의 고유 식별자)여야 합니다. 프로젝트 콘솔의 URL에서 확인할 수 있습니다. |
iss |
발급자 |
"https://securetoken.google.com/<projectId>" 여야 합니다. 여기에서 <projectId> 는 위 aud 에 사용된 프로젝트 ID와 동일합니다.
|
sub |
제목 |
비어 있지 않은 문자열이어야 하며 사용자 또는 기기의 uid 여야 합니다.
|
auth_time
|
인증 시간 | 과거 시간이어야 합니다. 사용자가 인증한 시간입니다. |
마지막으로, 토큰의 kid
클레임에 해당하는 비공개 키로 ID 토큰이 서명되었는지 확인합니다. https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com
에서 공개 키를 확인하고 JWT 라이브러리를 사용하여 서명을 검증합니다. 이 엔드포인트에서 보낸 응답의 Cache-Control
헤더에 있는 max-age
값을 사용하여 공개 키를 갱신할 시점을 파악합니다.
위 검증이 모두 성공하면 ID 토큰의 제목(sub
)을 해당 사용자 또는 기기의 uid
로 사용할 수 있습니다.