Tạo mã thông báo tuỳ chỉnh

Firebase cho phép bạn toàn quyền kiểm soát việc xác thực bằng cách cho phép bạn xác thực người dùng hoặc thiết bị bằng Mã thông báo web JSON (JWT) bảo mật. Bạn tạo các mã thông báo này trên máy chủ, chuyển chúng trở lại thiết bị khách, sau đó sử dụng chúng để xác thực thông qua phương thức signInWithCustomToken().

Để làm được điều này, bạn phải tạo một điểm cuối máy chủ chấp nhận thông tin đăng nhập (chẳng hạn như tên người dùng và mật khẩu) và nếu thông tin đăng nhập hợp lệ, hãy trả về một JWT tuỳ chỉnh. Sau đó, thiết bị khách có thể sử dụng JWT tuỳ chỉnh được trả về từ máy chủ của bạn để xác thực với Firebase (iOS+, Android, web). Sau khi được xác thực, danh tính này sẽ được dùng khi truy cập vào các dịch vụ khác của Firebase, chẳng hạn như Firebase Realtime Database và Cloud Storage. Hơn nữa, nội dung của JWT sẽ có trong đối tượng auth trong Realtime Database Security Rules và đối tượng request.auth trong Cloud Storage Security Rules.

Bạn có thể tạo mã thông báo tuỳ chỉnh bằng SDK của Firebase dành cho quản trị viên hoặc có thể sử dụng thư viện JWT của bên thứ ba nếu máy chủ của bạn được viết bằng một ngôn ngữ mà Firebase không hỗ trợ sẵn.

Trước khi bắt đầu

Mã thông báo tuỳ chỉnh là JWT đã ký, trong đó khoá riêng tư dùng để ký thuộc về một tài khoản dịch vụ của Google. Có một số cách để chỉ định tài khoản dịch vụ Google mà SDK của Firebase dành cho quản trị viên nên sử dụng để ký mã thông báo tuỳ chỉnh:

  • Cho phép SDK dành cho quản trị viên khám phá tài khoản dịch vụ – Bạn có thể sử dụng phương thức này trong các môi trường do Google quản lý, chẳng hạn như Cloud Functions và App Engine. Bạn có thể phải định cấu hình một số quyền bổ sung thông qua bảng điều khiển Google Cloud.
  • Sử dụng mã tài khoản dịch vụ – Phương thức này ký mã thông báo bằng các khoá do Google quản lý của tài khoản dịch vụ được chỉ định, vì vậy, bạn không cần phải tự xử lý bất kỳ khoá riêng tư nào. Tài khoản này sử dụng một dịch vụ web từ xa và bạn có thể phải định cấu hình các quyền bổ sung cho tài khoản dịch vụ này thông qua bảng điều khiển Google Cloud.
  • Sử dụng tệp khoá tài khoản dịch vụ – Chỉ sử dụng phương thức này nếu mã của bạn chạy bên ngoài môi trường do Google quản lý và bạn không thể sử dụng một trong hai phương thức nêu trên. Phương thức này yêu cầu bạn tạo, lưu trữ và bảo vệ một khoá riêng tư có thời hạn dài.

Bạn nên sử dụng hai phương thức đầu tiên vì không cần tải xuống hoặc quản lý khoá tài khoản dịch vụ.

Cho phép SDK dành cho quản trị viên khám phá tài khoản dịch vụ

Nếu mã của bạn được triển khai trong một môi trường do Google quản lý, thì SDK dành cho quản trị viên có thể cố gắng tự động khám phá một phương tiện để ký mã thông báo tuỳ chỉnh:

  • Nếu mã của bạn được triển khai trong môi trường tiêu chuẩn App Engine cho Java, Python hoặc Go, thì SDK dành cho quản trị viên có thể sử dụng dịch vụ Nhận dạng ứng dụng có trong môi trường đó để ký mã thông báo tuỳ chỉnh. Dịch vụ Nhận dạng ứng dụng ký dữ liệu bằng tài khoản dịch vụ do Google App Engine cung cấp cho ứng dụng của bạn.

  • Nếu mã của bạn được triển khai trong một số môi trường được quản lý khác (ví dụ: Google Cloud Functions, Google Compute Engine), thì SDK của Firebase dành cho quản trị viên có thể tự động khám phá chuỗi mã tài khoản dịch vụ từ máy chủ siêu dữ liệu cục bộ. Sau đó, mã tài khoản dịch vụ được phát hiện sẽ được dùng cùng với dịch vụ IAM để ký mã thông báo từ xa.

Để sử dụng các phương thức ký này, hãy khởi động SDK bằng Thông tin xác thực mặc định của ứng dụng Google và không chỉ định chuỗi mã tài khoản dịch vụ:

Node.js

initializeApp();

Java

FirebaseApp.initializeApp();

Python

default_app = firebase_admin.initialize_app()

Bắt đầu

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create();

Để kiểm thử cùng một mã trên máy mà không cần tải khoá tài khoản dịch vụ xuống, hãy đăng nhập bằng thông tin đăng nhập của người dùng bằng Google Cloud CLI:

gcloud auth application-default login

Vì không có máy chủ siêu dữ liệu trên máy cục bộ của bạn, nên SDK dành cho quản trị viên không thể tự động khám phá mã tài khoản dịch vụ ở đó. Thay vào đó, hãy chỉ định mã tài khoản dịch vụ khi bạn khởi chạy SDK và đảm bảo tài khoản người dùng của bạn có vai trò Người tạo mã thông báo tài khoản dịch vụ trên tài khoản dịch vụ đó.

Nếu SDK của Firebase dành cho quản trị viên phải khám phá chuỗi mã tài khoản dịch vụ, thì SDK này sẽ thực hiện việc đó khi mã của bạn tạo mã thông báo tuỳ chỉnh lần đầu tiên. Kết quả sẽ được lưu vào bộ nhớ đệm và sử dụng lại cho các thao tác ký mã thông báo tiếp theo. Mã tài khoản dịch vụ được tự động phát hiện thường là một trong các tài khoản dịch vụ mặc định do Google Cloud cung cấp:

Giống như mã tài khoản dịch vụ được chỉ định rõ ràng, mã tài khoản dịch vụ được tự động phát hiện phải có quyền iam.serviceAccounts.signBlob để tạo mã thông báo tuỳ chỉnh. Bạn có thể phải sử dụng mục IAM và quản trị viên của bảng điều khiển Google Cloud để cấp các quyền cần thiết cho tài khoản dịch vụ mặc định. Hãy xem phần khắc phục sự cố bên dưới để biết thêm thông tin chi tiết.

Sử dụng mã tài khoản dịch vụ

Để duy trì tính nhất quán giữa các phần khác nhau của ứng dụng, bạn có thể chỉ định một mã tài khoản dịch vụ có khoá do Google quản lý sẽ được dùng để ký mã thông báo. Điều này có thể giúp các chính sách IAM trở nên đơn giản và an toàn hơn, đồng thời tránh phải tải xuống, lưu trữ hoặc triển khai khoá tài khoản dịch vụ.

Bạn có thể tìm thấy mã tài khoản dịch vụ trong bảng điều khiển Google Cloud. Mã tài khoản dịch vụ là địa chỉ email có định dạng như sau: <client-id>@<project-id>.iam.gserviceaccount.com. Các mã này giúp xác định riêng biệt tài khoản dịch vụ trong Firebase và các dự án Google Cloud.

Để tạo mã thông báo tuỳ chỉnh bằng một mã tài khoản dịch vụ riêng biệt, hãy khởi chạy SDK như minh hoạ dưới đây:

Node.js

initializeApp({
  serviceAccountId: 'my-client-id@my-project-id.iam.gserviceaccount.com',
});

Java

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setServiceAccountId("my-client-id@my-project-id.iam.gserviceaccount.com")
    .build();
FirebaseApp.initializeApp(options);

Python

options = {
    'serviceAccountId': 'my-client-id@my-project-id.iam.gserviceaccount.com',
}
firebase_admin.initialize_app(options=options)

Bắt đầu

conf := &firebase.Config{
	ServiceAccountID: "my-client-id@my-project-id.iam.gserviceaccount.com",
}
app, err := firebase.NewApp(context.Background(), conf)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.GetApplicationDefault(),
    ServiceAccountId = "my-client-id@my-project-id.iam.gserviceaccount.com",
});

Mã tài khoản dịch vụ không phải là thông tin nhạy cảm, do đó, việc lộ mã này không gây ra hậu quả gì. Tuy nhiên, để ký mã thông báo tuỳ chỉnh bằng tài khoản dịch vụ được chỉ định, SDK của Firebase dành cho quản trị viên phải gọi một dịch vụ từ xa. Hơn nữa, bạn cũng phải đảm bảo rằng danh tính mà SDK dành cho quản trị viên đang sử dụng để thực hiện lệnh gọi này (thường là {project-name}@appspot.gserviceaccount.com trong môi trường thực tế hoặc tài khoản người dùng của riêng bạn trong quá trình phát triển cục bộ) có quyền iam.serviceAccounts.signBlob. Hãy xem phần khắc phục sự cố bên dưới để biết thêm thông tin chi tiết.

Sử dụng tệp khoá tài khoản dịch vụ

Nếu mã của bạn chạy trong một môi trường bên ngoài Google Cloud, nơi không có phương thức nào ở trên, thì bạn có thể khởi chạy SDK quản trị bằng tệp khoá tài khoản dịch vụ. Hãy làm theo hướng dẫn thiết lập SDK dành cho quản trị viên để biết thông tin chi tiết. Với phương thức này, SDK dành cho quản trị viên sẽ ký mã thông báo tuỳ chỉnh trên thiết bị bằng khoá riêng tư trong tệp mà không cần thực hiện lệnh gọi API từ xa.

Khoá tài khoản dịch vụ là thông tin xác thực có thời hạn sử dụng dài. Nếu khoá bị rò rỉ, bất kỳ ai có khoá này đều có thể đóng vai trò là tài khoản dịch vụ cho đến khi khoá bị xoá. Đừng bao giờ đưa các tệp khoá vào hệ thống quản lý phiên bản và hãy cân nhắc sử dụng Workload Identity Federation thay vì khoá nếu môi trường của bạn hỗ trợ. Ngoài ra, xin lưu ý rằng một số tổ chức sử dụng các quy tắc ràng buộc trong chính sách của tổ chức để ngăn chặn việc tạo khoá tài khoản dịch vụ. Trong trường hợp đó, bạn phải sử dụng một trong các phương thức khác.

Tạo mã thông báo tuỳ chỉnh bằng SDK của Firebase dành cho quản trị viên

SDK của Firebase dành cho quản trị viên có một phương thức tích hợp sẵn để tạo mã thông báo tuỳ chỉnh. Tối thiểu, bạn cần cung cấp một uid. Đây có thể là chuỗi bất kỳ nhưng phải xác định duy nhất người dùng hoặc thiết bị mà bạn đang xác thực. Các mã thông báo này sẽ hết hạn sau một giờ.

Node.js

const uid = 'some-uid';

getAuth()
  .createCustomToken(uid)
  .then((customToken) => {
    // Send token back to client
  })
  .catch((error) => {
    console.log('Error creating custom token:', error);
  });

Java

String uid = "some-uid";

String customToken = FirebaseAuth.getInstance().createCustomToken(uid);
// Send token back to client

Python

uid = 'some-uid'

custom_token = auth.create_custom_token(uid)

Bắt đầu

client, err := app.Auth(context.Background())
if err != nil {
	log.Fatalf("error getting Auth client: %v\n", err)
}

token, err := client.CustomToken(ctx, "some-uid")
if err != nil {
	log.Fatalf("error minting custom token: %v\n", err)
}

log.Printf("Got custom token: %v\n", token)

C#

var uid = "some-uid";

string customToken = await FirebaseAuth.DefaultInstance.CreateCustomTokenAsync(uid);
// Send token back to client

Bạn cũng có thể chỉ định thêm các thông báo xác nhận quyền sở hữu để đưa vào mã thông báo tuỳ chỉnh (không bắt buộc). Ví dụ: bên dưới, trường premiumAccount đã được thêm vào mã thông báo tuỳ chỉnh. Mã thông báo này sẽ có trong các đối tượng auth/request.auth trong Quy tắc bảo mật:

Node.js

const userId = 'some-uid';
const additionalClaims = {
  premiumAccount: true,
};

getAuth()
  .createCustomToken(userId, additionalClaims)
  .then((customToken) => {
    // Send token back to client
  })
  .catch((error) => {
    console.log('Error creating custom token:', error);
  });

Java

String uid = "some-uid";
Map<String, Object> additionalClaims = new HashMap<String, Object>();
additionalClaims.put("premiumAccount", true);

String customToken = FirebaseAuth.getInstance()
    .createCustomToken(uid, additionalClaims);
// Send token back to client

Python

uid = 'some-uid'
additional_claims = {
    'premiumAccount': True
}

custom_token = auth.create_custom_token(uid, additional_claims)

Bắt đầu

client, err := app.Auth(context.Background())
if err != nil {
	log.Fatalf("error getting Auth client: %v\n", err)
}

claims := map[string]interface{}{
	"premiumAccount": true,
}

token, err := client.CustomTokenWithClaims(ctx, "some-uid", claims)
if err != nil {
	log.Fatalf("error minting custom token: %v\n", err)
}

log.Printf("Got custom token: %v\n", token)

C#

var uid = "some-uid";
var additionalClaims = new Dictionary<string, object>()
{
    { "premiumAccount", true },
};

string customToken = await FirebaseAuth.DefaultInstance
    .CreateCustomTokenAsync(uid, additionalClaims);
// Send token back to client

Tên mã thông báo tuỳ chỉnh dành riêng

Đăng nhập bằng mã thông báo tuỳ chỉnh trên ứng dụng khách

Sau khi tạo mã thông báo tuỳ chỉnh, bạn nên gửi mã thông báo đó đến ứng dụng khách. Ứng dụng khách xác thực bằng mã thông báo tuỳ chỉnh bằng cách gọi signInWithCustomToken():

iOS+

Objective-C
[[FIRAuth auth] signInWithCustomToken:customToken
                           completion:^(FIRAuthDataResult * _Nullable authResult,
                                        NSError * _Nullable error) {
  // ...
}];
Swift
Auth.auth().signIn(withCustomToken: customToken ?? "") { user, error in
  // ...
}

Android

mAuth.signInWithCustomToken(mCustomToken)
        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // Sign in success, update UI with the signed-in user's information
                    Log.d(TAG, "signInWithCustomToken:success");
                    FirebaseUser user = mAuth.getCurrentUser();
                    updateUI(user);
                } else {
                    // If sign in fails, display a message to the user.
                    Log.w(TAG, "signInWithCustomToken:failure", task.getException());
                    Toast.makeText(CustomAuthActivity.this, "Authentication failed.",
                            Toast.LENGTH_SHORT).show();
                    updateUI(null);
                }
            }
        });

Unity

auth.SignInWithCustomTokenAsync(custom_token).ContinueWith(task => {
  if (task.IsCanceled) {
    Debug.LogError("SignInWithCustomTokenAsync was canceled.");
    return;
  }
  if (task.IsFaulted) {
    Debug.LogError("SignInWithCustomTokenAsync encountered an error: " + task.Exception);
    return;
  }

  Firebase.Auth.AuthResult result = task.Result;
  Debug.LogFormat("User signed in successfully: {0} ({1})",
      result.User.DisplayName, result.User.UserId);
});

C++

firebase::Future<firebase::auth::AuthResult> result =
    auth->SignInWithCustomToken(custom_token);

Web

firebase.auth().signInWithCustomToken(token)
  .then((userCredential) => {
    // Signed in
    var user = userCredential.user;
    // ...
  })
  .catch((error) => {
    var errorCode = error.code;
    var errorMessage = error.message;
    // ...
  });

Web

import { getAuth, signInWithCustomToken } from "firebase/auth";

const auth = getAuth();
signInWithCustomToken(auth, token)
  .then((userCredential) => {
    // Signed in
    const user = userCredential.user;
    // ...
  })
  .catch((error) => {
    const errorCode = error.code;
    const errorMessage = error.message;
    // ...
  });

Nếu quá trình xác thực thành công, người dùng của bạn hiện sẽ đăng nhập vào ứng dụng khách bằng tài khoản được chỉ định bởi uid có trong mã thông báo tuỳ chỉnh. Nếu tài khoản đó chưa tồn tại, thì hệ thống sẽ tạo một bản ghi cho người dùng đó.

Tương tự như các phương thức đăng nhập khác (chẳng hạn như signInWithEmailAndPassword() và signInWithCredential()), đối tượng auth trong Realtime Database Security Rules và đối tượng request.auth trong Cloud Storage Security Rules sẽ được điền sẵn uid của người dùng. Trong trường hợp này, uid sẽ là mã thông báo mà bạn đã chỉ định khi tạo mã thông báo tuỳ chỉnh.

Quy tắc cơ sở dữ liệu

{
  "rules": {
    "adminContent": {
      ".read": "auth.uid === 'some-uid'"
    }
  }
}

Quy tắc lưu trữ

service firebase.storage {
  match /b/<your-firebase-storage-bucket>/o {
    match /adminContent/{filename} {
      allow read, write: if request.auth != null && request.auth.uid == "some-uid";
    }
  }
}

Nếu mã thông báo tuỳ chỉnh chứa các thông báo xác nhận quyền sở hữu bổ sung, thì bạn có thể tham chiếu các thông báo đó từ đối tượng auth.token (Firebase Realtime Database) hoặc request.auth.token (Cloud Storage) trong quy tắc của mình:

Quy tắc cơ sở dữ liệu

{
  "rules": {
    "premiumContent": {
      ".read": "auth.token.premiumAccount === true"
    }
  }
}

Quy tắc lưu trữ

service firebase.storage {
  match /b/<your-firebase-storage-bucket>/o {
    match /premiumContent/{filename} {
      allow read, write: if request.auth.token.premiumAccount == true;
    }
  }
}

Tạo mã thông báo tuỳ chỉnh bằng thư viện JWT của bên thứ ba

Nếu phần phụ trợ của bạn sử dụng một ngôn ngữ không có SDK quản trị Firebase chính thức, thì bạn vẫn có thể tạo mã thông báo tuỳ chỉnh theo cách thủ công. Trước tiên, hãy tìm một thư viện JWT của bên thứ ba cho ngôn ngữ của bạn. Sau đó, hãy sử dụng thư viện JWT đó để tạo một JWT bao gồm các thông báo xác nhận quyền sở hữu sau:

Xác nhận quyền sở hữu mã thông báo tuỳ chỉnh
alg Thuật toán "RS256"
iss Tổ chức phát hành Địa chỉ email của tài khoản dịch vụ trong dự án của bạn
sub Chủ đề Địa chỉ email của tài khoản dịch vụ trong dự án của bạn
aud Đối tượng "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Thời gian phát hành Thời gian hiện tại, tính bằng giây kể từ thời gian Unix
exp Thời gian hết hạn Thời gian (tính bằng giây kể từ thời gian Unix) mà mã thông báo hết hạn. Giá trị này có thể muộn hơn tối đa 3.600 giây so với iat.
Lưu ý: thuộc tính này chỉ kiểm soát thời điểm mã thông báo tuỳ chỉnh hết hạn. Tuy nhiên, sau khi bạn đăng nhập cho người dùng bằng signInWithCustomToken(), họ sẽ vẫn đăng nhập vào thiết bị cho đến khi phiên của họ không hợp lệ hoặc người dùng đăng xuất.
uid Giá trị nhận dạng riêng biệt của người dùng đã đăng nhập phải là một chuỗi, có độ dài từ 1 đến 128 ký tự (bao gồm cả 1 và 128). uid ngắn hơn sẽ mang lại hiệu suất tốt hơn.
claims (không bắt buộc) Xác nhận quyền sở hữu tuỳ chỉnh không bắt buộc để đưa vào các biến auth / request.auth của Quy tắc bảo mật

Dưới đây là một số ví dụ về cách triển khai để tạo mã thông báo tuỳ chỉnh bằng nhiều ngôn ngữ mà SDK của Firebase dành cho quản trị viên không hỗ trợ. Các ví dụ này ký mã thông báo trên thiết bị bằng khoá riêng tư của tài khoản dịch vụ, vì vậy, hướng dẫn bảo mật cho tệp khoá tài khoản dịch vụ sẽ được áp dụng. Để tránh phải quản lý khoá riêng tư, bạn có thể yêu cầu Google ký tải trọng mã thông báo từ xa bằng cách gọi phương thức signJwt của API Thông tin đăng nhập tài khoản dịch vụ IAM. Phương thức gọi cần có vai trò Người tạo mã thông báo tài khoản dịch vụ trên tài khoản dịch vụ.

PHP

Sử dụng php-jwt:

// Requires: composer require firebase/php-jwt
use Firebase\JWT\JWT;

// Placeholder values. In production, load your service account's email
// address and private key from a secure secret store. Never hard-code
// private keys in source code.
$service_account_email = "abc-123@a-b-c-123.iam.gserviceaccount.com";
$private_key = "-----BEGIN PRIVATE KEY-----...";

function create_custom_token($uid, $is_premium_account) {
  global $service_account_email, $private_key;

  $now_seconds = time();
  $payload = array(
    "iss" => $service_account_email,
    "sub" => $service_account_email,
    "aud" => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
    "iat" => $now_seconds,
    "exp" => $now_seconds+(60*60),  // Maximum expiration time is one hour
    "uid" => $uid,
    "claims" => array(
      "premium_account" => $is_premium_account
    )
  );
  return JWT::encode($payload, $private_key, "RS256");
}

Ruby

Sử dụng ruby-jwt:

require "jwt"

# Placeholder values. In production, load your service account's email
# address and private key from a secure secret store. Never hard-code
# private keys in source code.
$service_account_email = "service-account@my-project-abc123.iam.gserviceaccount.com"
$private_key = OpenSSL::PKey::RSA.new "-----BEGIN PRIVATE KEY-----\n..."

def create_custom_token(uid, is_premium_account)
  now_seconds = Time.now.to_i
  payload = {:iss => $service_account_email,
             :sub => $service_account_email,
             :aud => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
             :iat => now_seconds,
             :exp => now_seconds+(60*60), # Maximum expiration time is one hour
             :uid => uid,
             :claims => {:premium_account => is_premium_account}}
  JWT.encode payload, $private_key, "RS256"
end

Sau khi tạo mã thông báo tuỳ chỉnh, hãy gửi mã đó đến ứng dụng khách để dùng cho việc xác thực bằng Firebase. Hãy xem các mã mẫu ở trên để biết cách thực hiện việc này.

Khắc phục sự cố

Phần này trình bày một số vấn đề phổ biến mà nhà phát triển có thể gặp phải khi tạo mã thông báo tuỳ chỉnh và cách giải quyết các vấn đề đó.

Chưa bật IAM API

Nếu đang chỉ định mã tài khoản dịch vụ để ký mã thông báo, bạn có thể gặp lỗi tương tự như sau:

Identity and Access Management (IAM) API has not been used in project
1234567890 before or it is disabled. Enable it by visiting
https://console.developers.google.com/apis/api/iam.googleapis.com/overview?project=1234567890
then retry. If you enabled this API recently, wait a few minutes for the action
to propagate to our systems and retry.

SDK của Firebase dành cho quản trị viên sử dụng IAM API để ký mã thông báo. Lỗi này cho biết API IAM hiện chưa được bật cho dự án Firebase của bạn. Mở đường liên kết trong thông báo lỗi trong trình duyệt web rồi nhấp vào nút "Enable API" (Bật API) để bật API cho dự án của bạn.

Tài khoản dịch vụ không có các quyền cần thiết

Nếu tài khoản dịch vụ mà SDK của Firebase dành cho quản trị viên đang chạy không có quyền iam.serviceAccounts.signBlob, thì bạn có thể nhận được thông báo lỗi như sau:

Permission iam.serviceAccounts.signBlob is required to perform this operation
on service account projects/-/serviceAccounts/{your-service-account-id}.

Để giải quyết vấn đề này, hãy cấp vai trò IAM Người tạo mã thông báo tài khoản dịch vụ cho tài khoản dịch vụ thích hợp. Tài khoản dịch vụ mặc định được sử dụng phụ thuộc vào môi trường và phiên bản Cloud Functions:

  • Cloud Functions (thế hệ thứ 1): Sử dụng tài khoản dịch vụ mặc định của App Engine.
  • Cloud Functions (thế hệ thứ 2): Sử dụng tài khoản dịch vụ mặc định của Compute Engine.
  1. Trong bảng điều khiển Google Cloud, hãy chuyển đến phần IAM and Admin (IAM và Quản trị viên).

  2. Nhấp vào biểu tượng chỉnh sửa tương ứng với tài khoản dịch vụ mà bạn muốn cập nhật.

  3. Nhấp vào Thêm vai trò khác.

  4. Nhập "Service Account Token Creator" vào bộ lọc tìm kiếm rồi chọn bộ lọc đó trong kết quả.

  5. Nhấp vào Lưu để xác nhận việc cấp vai trò.

Tham khảo tài liệu về IAM để biết thêm thông tin chi tiết về quy trình này hoặc tìm hiểu cách cập nhật vai trò bằng công cụ dòng lệnh gcloud.

Không xác định được tài khoản dịch vụ

Nếu bạn nhận được thông báo lỗi tương tự như sau, thì tức là SDK của Firebase dành cho quản trị viên chưa được khởi chạy đúng cách.

Failed to determine service account ID. Initialize the SDK with service account
credentials or specify a service account ID with iam.serviceAccounts.signBlob
permission.

Nếu bạn đang dựa vào SDK để tự động khám phá mã tài khoản dịch vụ, hãy đảm bảo mã được triển khai trong môi trường Google được quản lý có máy chủ siêu dữ liệu. Nếu không, hãy nhớ chỉ định mã tài khoản dịch vụ khi khởi chạy SDK hoặc khởi chạy SDK bằng tệp khoá tài khoản dịch vụ trong môi trường không phải của Google.