Ikuti semua informasi yang diumumkan di Firebase Summit, dan pelajari bagaimana Firebase dapat membantu Anda mempercepat pengembangan aplikasi dan menjalankan aplikasi dengan percaya diri. Pelajari Lebih Lanjut

Buat Token Khusus

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

Firebase memberi Anda kendali penuh atas autentikasi dengan mengizinkan Anda mengautentikasi pengguna atau perangkat menggunakan JSON Web Token (JWT) yang aman. Anda membuat token ini di server Anda, meneruskannya kembali ke perangkat klien, lalu menggunakannya untuk mengautentikasi melalui metode signInWithCustomToken() .

Untuk mencapai ini, Anda harus membuat titik akhir server yang menerima kredensial masuk—seperti nama pengguna dan kata sandi—dan, jika kredensial valid, mengembalikan JWT khusus. JWT khusus yang dikembalikan dari server Anda kemudian dapat digunakan oleh perangkat klien untuk mengautentikasi dengan Firebase ( iOS+ , Android , web ). Setelah diautentikasi, identitas ini akan digunakan saat mengakses layanan Firebase lainnya, seperti Firebase Realtime Database dan Cloud Storage. Selain itu, konten JWT akan tersedia di objek auth di Aturan Database Realtime Anda dan objek request.auth di Aturan Keamanan Cloud Storage Anda.

Anda dapat membuat token khusus dengan Firebase Admin SDK, atau Anda dapat menggunakan pustaka JWT pihak ketiga jika server Anda ditulis dalam bahasa yang tidak didukung secara asli oleh Firebase.

Sebelum kamu memulai

Token khusus adalah JWT yang ditandatangani di mana kunci pribadi yang digunakan untuk penandatanganan adalah milik akun layanan Google. Ada beberapa cara untuk menentukan akun layanan Google yang harus digunakan oleh Firebase Admin SDK untuk menandatangani token khusus:

  • Menggunakan file JSON akun layanan -- Metode ini dapat digunakan di lingkungan apa pun, tetapi mengharuskan Anda mengemas file JSON akun layanan bersama dengan kode Anda. Perhatian khusus harus diberikan untuk memastikan bahwa file JSON akun layanan tidak diekspos ke pihak eksternal.
  • Membiarkan SDK Admin menemukan akun layanan -- Metode ini dapat digunakan di lingkungan yang dikelola oleh Google seperti Google Cloud Functions dan App Engine. Anda mungkin harus mengonfigurasi beberapa izin tambahan melalui Google Cloud Console.
  • Menggunakan ID akun layanan -- Saat digunakan di lingkungan yang dikelola Google, metode ini akan menandatangani token menggunakan kunci akun layanan yang ditentukan. Namun, ini menggunakan layanan web jarak jauh, dan Anda mungkin harus mengonfigurasi izin tambahan untuk akun layanan ini melalui Google Cloud Console.

Menggunakan file JSON akun layanan

File JSON akun layanan berisi semua informasi yang terkait dengan akun layanan (termasuk kunci pribadi RSA). Mereka dapat diunduh dari konsol Firebase. Ikuti petunjuk penyiapan Admin SDK untuk informasi lebih lanjut tentang cara menginisialisasi Admin SDK dengan file JSON akun layanan.

Metode inisialisasi ini cocok untuk berbagai penerapan Admin SDK. Juga memungkinkan Admin SDK untuk membuat dan menandatangani token khusus secara lokal, tanpa melakukan panggilan API jarak jauh. Kelemahan utama dari pendekatan ini adalah Anda harus mengemas file JSON akun layanan bersama dengan kode Anda. Perhatikan juga bahwa kunci pribadi dalam file JSON akun layanan adalah informasi sensitif, dan perhatian khusus harus diberikan untuk menjaga kerahasiaannya. Secara khusus, hindari menambahkan file JSON akun layanan ke kontrol versi publik.

Membiarkan Admin SDK menemukan akun layanan

Jika kode Anda diterapkan di lingkungan yang dikelola oleh Google, Admin SDK dapat mencoba menemukan cara otomatis untuk menandatangani token khusus:

  • Jika kode Anda diterapkan di lingkungan standar App Engine untuk Java, Python, atau Go, Admin SDK dapat menggunakan layanan App Identity yang ada di lingkungan tersebut untuk menandatangani token khusus. Layanan App Identity menandatangani data menggunakan akun layanan yang disediakan untuk aplikasi Anda oleh Google App Engine.

  • Jika kode Anda diterapkan di beberapa lingkungan terkelola lainnya (mis. Google Cloud Functions, Google Compute Engine), Firebase Admin SDK dapat menemukan string ID akun layanan secara otomatis dari server metadata lokal . ID akun layanan yang ditemukan kemudian digunakan bersama dengan layanan IAM untuk menandatangani token dari jarak jauh.

Untuk menggunakan metode penandatanganan ini, lakukan inisialisasi SDK dengan kredensial Default Aplikasi Google dan jangan tentukan string ID akun layanan:

Node.js

initializeApp();

Jawa

FirebaseApp.initializeApp();

Piton

default_app = firebase_admin.initialize_app()

Pergi

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

C#

FirebaseApp.Create();

Untuk menguji kode yang sama secara lokal, unduh file JSON akun layanan dan setel variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS untuk mengarah ke sana.

Jika Firebase Admin SDK harus menemukan string ID akun layanan, hal itu dilakukan saat kode Anda membuat token khusus untuk pertama kalinya. Hasilnya di-cache dan digunakan kembali untuk operasi penandatanganan token berikutnya. ID akun layanan yang ditemukan secara otomatis biasanya merupakan salah satu akun layanan default yang disediakan oleh Google Cloud:

Sama seperti dengan ID akun layanan yang ditentukan secara eksplisit, ID akun layanan yang ditemukan secara otomatis harus memiliki izin iam.serviceAccounts.signBlob agar pembuatan token kustom berfungsi. Anda mungkin harus menggunakan bagian IAM dan admin Google Cloud Console untuk memberikan izin yang diperlukan kepada akun layanan default. Lihat bagian pemecahan masalah di bawah ini untuk detail lebih lanjut.

Menggunakan ID akun layanan

Untuk menjaga konsistensi antara berbagai bagian aplikasi, Anda dapat menentukan ID akun layanan yang kuncinya akan digunakan untuk menandatangani token saat berjalan di lingkungan yang dikelola Google. Hal ini dapat membuat kebijakan IAM lebih sederhana dan lebih aman, serta menghindari keharusan menyertakan file JSON akun layanan dalam kode Anda.

ID akun layanan dapat ditemukan di Google Cloud Console , atau di kolom client_email dari file JSON akun layanan yang diunduh. ID akun layanan adalah alamat email yang memiliki format berikut: <client-id>@<project-id>.iam.gserviceaccount.com . Mereka secara unik mengidentifikasi akun layanan di proyek Firebase dan Google Cloud.

Untuk membuat token khusus menggunakan ID akun layanan terpisah, lakukan inisialisasi SDK seperti yang ditunjukkan di bawah ini:

Node.js

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

Jawa

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

Piton

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

Pergi

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",
});

ID akun layanan bukanlah informasi sensitif dan oleh karena itu keterpaparannya tidak penting. Namun, untuk menandatangani token khusus dengan akun layanan yang ditentukan, Firebase Admin SDK harus memanggil layanan jarak jauh. Selain itu, Anda juga harus memastikan bahwa akun layanan yang digunakan Admin SDK untuk melakukan panggilan ini —biasanya {project-name}@appspot.gserviceaccount.com — memiliki izin iam.serviceAccounts.signBlob . Lihat bagian pemecahan masalah di bawah ini untuk detail lebih lanjut.

Buat token khusus menggunakan Firebase Admin SDK

Firebase Admin SDK memiliki metode bawaan untuk membuat token khusus. Minimal, Anda perlu menyediakan uid , yang dapat berupa string apa pun tetapi harus secara unik mengidentifikasi pengguna atau perangkat yang Anda autentikasi. Token ini kedaluwarsa setelah satu jam.

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);
  });

Jawa

String uid = "some-uid";

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

Piton

uid = 'some-uid'

custom_token = auth.create_custom_token(uid)

Pergi

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

Secara opsional, Anda juga dapat menentukan klaim tambahan untuk disertakan dalam token kustom. Misalnya, di bawah ini, bidang premiumAccount telah ditambahkan ke token khusus, yang akan tersedia di objek auth / request.auth di Aturan Keamanan Anda:

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);
  });

Jawa

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

Piton

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

custom_token = auth.create_custom_token(uid, additional_claims)

Pergi

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

Nama token khusus yang dipesan

Masuk menggunakan token khusus pada klien

Setelah Anda membuat token khusus, Anda harus mengirimkannya ke aplikasi klien Anda. Aplikasi klien mengautentikasi dengan token khusus dengan memanggil signInWithCustomToken() :

iOS+

Objective-C
[[FIRAuth auth] signInWithCustomToken:customToken
                           completion:^(FIRAuthDataResult * _Nullable authResult,
                                        NSError * _Nullable error) {
  // ...
}];
Cepat
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);
                }
            }
        });

Persatuan

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.FirebaseUser newUser = task.Result;
  Debug.LogFormat("User signed in successfully: {0} ({1})",
      newUser.DisplayName, newUser.UserId);
});

C++

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

Web version 8

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

Web version 9

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;
    // ...
  });

Jika autentikasi berhasil, pengguna Anda sekarang akan masuk ke aplikasi klien Anda dengan akun yang ditentukan oleh uid yang disertakan dalam token khusus. Jika akun tersebut sebelumnya tidak ada, rekaman untuk pengguna tersebut akan dibuat.

Dengan cara yang sama seperti metode masuk lainnya (seperti signInWithEmailAndPassword() dan signInWithCredential() ), objek auth di Aturan Database Realtime dan objek request.auth di Aturan Keamanan Cloud Storage Anda akan diisi dengan uid pengguna. Dalam hal ini, uid akan menjadi yang Anda tentukan saat membuat token khusus.

Aturan Basis Data

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

Aturan Penyimpanan

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";
    }
  }
}

Jika token khusus berisi klaim tambahan, klaim tersebut dapat dirujuk dari auth.token (Firebase Realtime Database) atau request.auth.token (Cloud Storage) dalam aturan Anda:

Aturan Basis Data

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

Aturan Penyimpanan

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

Buat token khusus menggunakan pustaka JWT pihak ketiga

Jika backend Anda menggunakan bahasa yang tidak memiliki Firebase Admin SDK resmi, Anda tetap dapat membuat token khusus secara manual. Pertama, temukan pustaka JWT pihak ketiga untuk bahasa Anda. Kemudian, gunakan pustaka JWT tersebut untuk membuat JWT yang menyertakan klaim berikut:

Klaim Token Kustom
alg Algoritma "RS256"
iss Emiten Alamat email akun layanan proyek Anda
sub Subjek Alamat email akun layanan project Anda
aud Hadirin "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Dikeluarkan-pada waktu Waktu saat ini, dalam detik sejak zaman UNIX
exp Waktu kedaluwarsa Waktu, dalam detik sejak zaman UNIX, saat token kedaluwarsa. Bisa maksimal 3600 detik lebih lambat dari iat .
Catatan: ini hanya mengontrol waktu kapan token kustom itu sendiri kedaluwarsa. Namun setelah Anda membuat pengguna masuk menggunakan signInWithCustomToken() , mereka akan tetap masuk ke perangkat hingga sesi mereka dibatalkan validasinya atau pengguna keluar.
uid Pengidentifikasi unik dari pengguna yang masuk harus berupa string, antara 1-128 karakter, inklusif. uid yang lebih pendek menawarkan kinerja yang lebih baik.
claims (opsional) Klaim kustom opsional untuk disertakan dalam variabel auth / request.auth Aturan Keamanan

Berikut adalah beberapa contoh penerapan cara membuat token khusus dalam berbagai bahasa yang tidak didukung oleh Firebase Admin SDK:

PHP

Menggunakan php-jwt :

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

// Get your service account's email address and private key from the JSON key file
$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");
}

Rubi

Menggunakan ruby-jwt :

require "jwt"

# Get your service account's email address and private key from the JSON key file
$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

Setelah Anda membuat token khusus, kirimkan ke aplikasi klien Anda untuk digunakan untuk mengautentikasi dengan Firebase. Lihat contoh kode di atas untuk cara melakukannya.

Penyelesaian masalah

Bagian ini menguraikan beberapa masalah umum yang mungkin dihadapi developer saat membuat token kustom, dan cara mengatasinya.

API IAM tidak diaktifkan

Jika Anda menentukan ID akun layanan untuk menandatangani token, Anda mungkin mendapatkan kesalahan yang serupa dengan berikut ini:

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.

Firebase Admin SDK menggunakan IAM API untuk menandatangani token. Error ini menunjukkan bahwa IAM API saat ini tidak diaktifkan untuk project Firebase Anda. Buka tautan dalam pesan kesalahan di browser web, dan klik tombol "Aktifkan API" untuk mengaktifkannya untuk proyek Anda.

Akun layanan tidak memiliki izin yang diperlukan

Jika akun layanan yang menjalankan Firebase Admin SDK tidak memiliki izin iam.serviceAccounts.signBlob , Anda mungkin mendapatkan pesan error seperti berikut:

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

Cara termudah untuk menyelesaikan ini adalah dengan memberikan peran IAM "Pembuat Token Akun Layanan" ke akun layanan yang bersangkutan, biasanya {project-name}@appspot.gserviceaccount.com :

  1. Buka halaman IAM dan admin di Google Cloud Console.
  2. Pilih proyek Anda dan klik "Lanjutkan".
  3. Klik ikon edit yang sesuai dengan akun layanan yang ingin Anda perbarui.
  4. Klik "Tambahkan Peran Lain".
  5. Ketik "Pembuat Token Akun Layanan" ke dalam filter pencarian, dan pilih dari hasil.
  6. Klik "Simpan" untuk mengonfirmasi pemberian peran.

Lihat dokumentasi IAM untuk detail lebih lanjut tentang proses ini, atau pelajari cara memperbarui peran menggunakan alat baris perintah gcloud.

Gagal menentukan akun layanan

Jika Anda mendapatkan pesan error yang serupa dengan berikut, berarti Firebase Admin SDK belum diinisialisasi dengan benar.

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

Jika Anda mengandalkan SDK untuk menemukan ID akun layanan secara otomatis, pastikan kode diterapkan di lingkungan Google terkelola dengan server metadata. Jika tidak, pastikan untuk menentukan file JSON akun layanan atau ID akun layanan pada inisialisasi SDK.