Trong bản xem trước công khai Firebase PNV, Firebase Authentication không thể trực tiếp chấp nhận mã thông báo Firebase PNV để đăng nhập; tuy nhiên, bạn có thể cho phép người dùng đăng nhập bằng Firebase PNV bằng cách sử dụng tính năng xác thực tuỳ chỉnh của Firebase Authentication.
Tạo một điểm cuối trao đổi mã thông báo
Bước quan trọng trong việc triển khai một giải pháp xác thực tuỳ chỉnh trong Firebase là tạo một điểm cuối có thể nhận mã thông báo Firebase PNV, xác thực mã thông báo đó, rồi phát hành mã thông báo xác thực tuỳ chỉnh của Firebase. Sau đó, ứng dụng của bạn có thể dùng mã thông báo tuỳ chỉnh này để đăng nhập người dùng.
Điểm cuối này có thể được lưu trữ trên bất kỳ nền tảng nào, nhưng trong ví dụ sau, điểm cuối được lưu trữ bằng Cloud Functions cho Firebase:
Node.js
import { JwtVerifier } from "aws-jwt-verify";
import { getApp } from "firebase-admin/app";
import { getAuth, UserRecord } from "firebase-admin/auth";
import { onRequest } from "firebase-functions/https";
// Because we're deploying to Cloud Functions for Firebase, admin credentials
// are automatically available.
const app = getApp();
const authAdmin = getAuth(app);
// Find your Firebase project number in the Firebase console.
const FIREBASE_PROJECT_NUMBER = "123456789";
// The issuer and audience claims of the FPNV token are specific to your
// project.
const issuer = `https://fpnv.googleapis.com/projects/${FIREBASE_PROJECT_NUMBER}`;
const audience = `https://fpnv.googleapis.com/projects/${FIREBASE_PROJECT_NUMBER}`;
// The JWKS URL contains the current public signing keys for FPNV tokens.
const jwksUri = "https://fpnv.googleapis.com/v1beta/jwks";
// Configure a JWT verifier to check the following:
// - The token is signed by Google
// - The issuer and audience claims match your project
// - The token has not yet expired (default begavior)
const fpnvVerifier = JwtVerifier.create({ issuer, audience, jwksUri });
// This Cloud Function is your token exchange endpoint. You pass the endpoint an
// FPNV token, and the Cloud Function verifies it and exchanges it for a
// Firebase Auth token corresponding to the same user.
export const signInWithFpnv = onRequest(async (req, res) => {
// Get the FPNV token from the request body.
const fpnvToken = req.body?;
if (!fpnvToken) {
res.sendStatus(400);
return;
}
let verifiedPhoneNumber;
try {
// Attempt to verify the token using the verifier configured above.
const verifiedPayload = await fpnvVerifier.verify(fpnvToken);
// If verification succeeds, the subject claim of the token contains the
// verified phone number.
verifiedPhoneNumber = verifiedPayload.sub;
} catch {
// If verification fails, reject the token.
res.sendStatus(403);
return;
}
// Now that you have a verified phone number, look it up in your Firebase
// project's user database.
let user: UserRecord;
try {
// If a user account already exists with the phone number, retrieve it.
user = await authAdmin.getUserByPhoneNumber(verifiedPhoneNumber);
} catch {
// Otherwise, create a new user account using the phone number.
user = await authAdmin.createUser({phoneNumber: verifiedPhoneNumber});
}
// Finally, mint a Firebase custom auth token containing the UID of the user
// you looked up or created. Return this token to the caller.
const authToken = await authAdmin.createCustomToken(user.uid);
res.status(200).send(authToken);
return;
});
Đăng nhập bằng mã xác thực tuỳ chỉnh
Sau khi triển khai điểm cuối, hãy đăng nhập người dùng vào Firebase bằng cách làm theo các bước sau:
Lấy mã thông báo Firebase PNV bằng quy trình được mô tả trên trang Bắt đầu sử dụng Firebase Phone Number Verification.
Truyền mã thông báo này đến điểm cuối Cloud Functions. Điểm cuối sẽ trả về cho ứng dụng của bạn một mã thông báo xác thực tuỳ chỉnh mà bạn có thể truyền đến
signInWithCustomToken()
.Ví dụ: bạn có thể dùng Retrofit để viết một phương thức,
signInWithFpnvToken()
, có giao diện tương tự như một trong các phương thứcsignin
của Firebase:Kotlin
class FpnvSigninExample { interface FPNVTokenExchangeService { @POST("signInWithFpnv") suspend fun signInWithFpnv(@Body fpnvToken: String): String } val retrofit = Retrofit.Builder() .baseUrl("https://example-project.cloudfunctions.net/") .build() val service: FPNVTokenExchangeService = retrofit.create(FPNVTokenExchangeService::class.java) suspend fun signInWithFpnvToken(fpnvToken: String): Task<AuthResult?> = coroutineScope { val authToken = service.signInWithFpnv(fpnvToken) return@coroutineScope Firebase.auth.signInWithCustomToken(authToken) } }