Benutzerdefinierte Token erstellen Token

Firebase gibt Ihnen die vollständige Kontrolle über die Authentifizierung, indem Sie Benutzer oder Geräte mit sicheren JSON Web Tokens (JWTs) authentifizieren können. Sie erzeugen diese Token auf Ihrem Server, geben sie nicht an einem Client - Gerät zurück, und sie dann über die zur Authentifizierung verwenden signInWithCustomToken() Methode.

Um dies zu erreichen, müssen Sie einen Serverendpunkt erstellen, der Anmeldeinformationen wie Benutzername und Kennwort akzeptiert und, wenn die Anmeldeinformationen gültig sind, ein benutzerdefiniertes JWT zurückgibt. Der Brauch JWT von Ihrem Server zurückgegeben wird, kann dann von einem Client - Gerät verwendet werden , um mit Firebase (zum Authentifizieren iOS , Android , Web ). Nach der Authentifizierung wird diese Identität beim Zugriff auf andere Firebase-Dienste wie die Firebase Realtime Database und Cloud Storage verwendet. Darüber hinaus wird der Inhalt des JWT in dem zur Verfügung auth Objekt in Echtzeit Datenbank - request.auth Regeln und das request.auth Objekt in Ihren Cloud Storage Sicherheitsregeln .

Sie können mit dem Firebase Admin SDK ein benutzerdefiniertes Token erstellen oder eine JWT-Bibliothek eines Drittanbieters verwenden, wenn Ihr Server in einer Sprache geschrieben ist, die Firebase nicht nativ unterstützt.

Bevor Sie beginnen

Benutzerdefinierte Token sind signierte JWTs, bei denen der zum Signieren verwendete private Schlüssel zu einem Google-Dienstkonto gehört. Es gibt mehrere Möglichkeiten, das Google-Dienstkonto anzugeben, das vom Firebase Admin SDK zum Signieren benutzerdefinierter Token verwendet werden soll:

  • Mit einem Dienstkonto JSON - Datei - zusammen mit Ihrem Code Diese Methode kann in jeder Umgebung eingesetzt werden, sondern erfordert , dass Sie ein Dienstkonto JSON - Datei verpacken. Es muss besonders darauf geachtet werden, dass die JSON-Datei des Dienstkontos nicht für externe Parteien offengelegt wird.
  • Überlassen Sie die Admin SDK ein Dienstkonto entdecken - Diese Methode kann in Umgebungen von Google wie Google Cloud - Funktionen und App Engine verwaltet werden. Möglicherweise müssen Sie einige zusätzliche Berechtigungen über die Google Cloud Console konfigurieren.
  • Mit einem Service - Account - ID - Wenn in einem Google-verwalteten Umgebung verwendet diese Methode Token unterzeichnen den angegebenen Dienstkonto des Schlüssels. Es verwendet jedoch einen Remote-Webdienst, und Sie müssen möglicherweise zusätzliche Berechtigungen für dieses Dienstkonto über die Google Cloud Console konfigurieren.

Verwenden einer JSON-Datei für ein Dienstkonto

Dienstkonto-JSON-Dateien enthalten alle Informationen zu Dienstkonten (einschließlich des privaten RSA-Schlüssels). Sie können von der Firebase-Konsole heruntergeladen werden. Folgen Sie der Admin SDK einrichten Anweisungen für weitere Informationen, wie das Admin SDK mit einem Dienstkonto JSON - Datei zu initialisieren.

Diese Initialisierungsmethode eignet sich für eine Vielzahl von Admin SDK-Bereitstellungen. Außerdem ermöglicht es dem Admin SDK, benutzerdefinierte Token lokal zu erstellen und zu signieren, ohne Remote-API-Aufrufe durchzuführen. Der Hauptnachteil dieses Ansatzes besteht darin, dass Sie eine Dienstkonto-JSON-Datei zusammen mit Ihrem Code packen müssen. Beachten Sie auch, dass der private Schlüssel in einer JSON-Datei eines Dienstkontos vertrauliche Informationen ist, und dass besondere Sorgfalt darauf verwendet werden muss, ihn vertraulich zu behandeln. Vermeiden Sie insbesondere das Hinzufügen von JSON-Dateien für Dienstkonten zur öffentlichen Versionskontrolle.

Zulassen, dass das Admin SDK ein Dienstkonto erkennt

Wenn Ihr Code in einer von Google verwalteten Umgebung bereitgestellt wird, kann das Admin SDK versuchen, automatisch eine Möglichkeit zum Signieren benutzerdefinierter Token zu ermitteln:

  • Wenn Ihr Code in der App Engine Standardumgebung für Java, Python oder Go bereitgestellt wird, kann das Admin SDK die Verwendung App Identitätsdienst in dieser Umgebung , um benutzerdefinierte Token zu unterzeichnen. Der App Identity-Dienst signiert Daten mit einem Dienstkonto, das von Google App Engine für Ihre App bereitgestellt wird.

  • Wenn Ihr Code in einer anderen verwalteten Umgebung (zB Google Cloud - Funktionen, Google Compute Engine) eingesetzt wird, entdeckt Auto-das Firebase Admin SDK kann einen Dienstkonto - ID - String aus dem lokalen Metadatenserver . Die ermittelte Dienstkonto-ID wird dann in Verbindung mit dem IAM-Dienst verwendet, um Token remote zu signieren.

Um diese Signaturmethoden zu verwenden, initialisieren Sie das SDK mit den Google Application Default-Anmeldedaten und geben Sie keine Dienstkonto-ID-Zeichenfolge an:

Node.js

admin.initializeApp();

Java

FirebaseApp.initializeApp();

Python

default_app = firebase_admin.initialize_app()

gehen

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

C#

FirebaseApp.Create();

Um zu testen , vor Ort den gleichen Code, laden Sie ein Dienstkonto JSON - Datei und legen Sie den GOOGLE_APPLICATION_CREDENTIALS Umgebungsvariable Punkt zu.

Wenn das Firebase Admin SDK eine Dienstkonto-ID-Zeichenfolge ermitteln muss, geschieht dies, wenn Ihr Code zum ersten Mal ein benutzerdefiniertes Token erstellt. Das Ergebnis wird zwischengespeichert und für nachfolgende Tokensignaturvorgänge wiederverwendet. Die automatisch ermittelte Dienstkonto-ID ist normalerweise eines der Standarddienstkonten, die von der Google Cloud bereitgestellt werden:

Genau wie mit explizit angegebenen Dienstkonto - IDs, Auto-Discoverd Dienstkonto - IDs müssen die haben iam.serviceAccounts.signBlob Erlaubnis für die benutzerdefinierte Token Schöpfung an die Arbeit. Sie können die Installation müssen IAM und Admin Abschnitt der Google Cloud Console die Standarddienst zu gewähren , die erforderlichen Berechtigungen Konten. Weitere Informationen finden Sie im Abschnitt zur Fehlerbehebung unten.

Verwenden einer Dienstkonto-ID

Um die Konsistenz zwischen verschiedenen Teilen Ihrer Anwendung zu gewährleisten, können Sie eine Dienstkonto-ID angeben, deren Schlüssel zum Signieren von Token verwendet werden, wenn sie in einer von Google verwalteten Umgebung ausgeführt wird. Dadurch können IAM-Richtlinien einfacher und sicherer werden und es wird vermieden, dass die JSON-Datei des Dienstkontos in Ihren Code eingeschlossen werden muss.

Das Dienstkonto - ID kann in dem gefunden wird Google Cloud Console oder im client_email Feld einer heruntergeladenen Dienstkonto JSON - Datei. Service - Konto - IDs sind E - Mail - Adressen , die das folgende Format haben: <client-id>@<project-id>.iam.gserviceaccount.com . Sie identifizieren Dienstkonten in Firebase- und Google Cloud-Projekten eindeutig.

Um benutzerdefinierte Token mit einer separaten Dienstkonto-ID zu erstellen, initialisieren Sie das SDK wie unten gezeigt:

Node.js

admin.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)

gehen

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

Dienstkonto-IDs sind keine vertraulichen Informationen und ihre Offenlegung ist daher belanglos. Um jedoch benutzerdefinierte Token mit dem angegebenen Dienstkonto zu signieren, muss das Firebase Admin SDK einen Remotedienst aufrufen. Darüber hinaus müssen Sie auch sicherstellen, dass das Dienstkonto das Admin SDK diesen Aufruf -Normalerweise machen wird mit {project-name}@appspot.gserviceaccount.com - hat die iam.serviceAccounts.signBlob Erlaubnis . Weitere Informationen finden Sie im Abschnitt zur Fehlerbehebung unten.

Erstellen Sie benutzerdefinierte Token mit dem Firebase Admin SDK

Das Firebase Admin SDK verfügt über eine integrierte Methode zum Erstellen benutzerdefinierter Token. Zumindest müssen Sie die Bereitstellung eines uid , die eine beliebige Zeichenfolge sein kann, sollte aber eindeutig identifizieren den Benutzer oder Geräte , die Sie authentifizieren. Diese Token laufen nach einer Stunde ab.

Node.js

const uid = 'some-uid';

admin
  .auth()
  .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)

gehen

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

Sie können optional auch zusätzliche Ansprüche angeben, die in das benutzerdefinierte Token aufgenommen werden sollen. Zum Beispiel unten, ein premiumAccount hat Feld die benutzerdefinierten Token hinzugefügt worden, die in den zur Verfügung stehen werden auth / request.auth Objekte in den Sicherheitsregeln:

Node.js

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

admin
  .auth()
  .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)

gehen

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

Melden Sie sich mit benutzerdefinierten Token auf Clients an

Nachdem Sie ein benutzerdefiniertes Token erstellt haben, sollten Sie es an Ihre Client-App senden. Die Client - Anwendung authentifiziert mit dem benutzerdefinierten Token durch den Aufruf signInWithCustomToken() :

iOS

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

Einheit

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

Netz

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

Wenn die Authentifizierung erfolgreich ist , werden Ihre Benutzer jetzt in App in Ihrem Client mit dem durch den angegebene Konto zu unterzeichnen uid in den benutzerdefinierten Token enthalten. Wenn dieses Konto zuvor nicht existierte, wird ein Datensatz für diesen Benutzer erstellt.

Auf die gleiche Weise wie bei anderer Anmelde-Methoden (wie signInWithEmailAndPassword() und signInWithCredential() ) das auth Objekt in Echtzeit Datenbank - request.auth uid Regeln und das request.auth Objekt in Ihren Cloud Storage Sicherheitsregeln werden mit dem Benutzer bestückt werden uid . In diesem Fall wird die uid wird derjenige sein , dass Sie beim den benutzerdefinierten Token zu erzeugen.

Datenbankregeln

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

Aufbewahrungsregeln

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

Wenn das benutzerdefinierte Token zusätzliche Ansprüche enthält, können sie referenziert aus der seinen auth.token (Firebase Realtime - Datenbank) oder request.auth.token in Ihren Regeln (Cloud Storage) Objekt:

Datenbankregeln

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

Aufbewahrungsregeln

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

Erstellen Sie benutzerdefinierte Token mit einer JWT-Bibliothek eines Drittanbieters

Wenn Ihr Back-End in einer Sprache vorliegt, für die kein offizielles Firebase Admin SDK vorhanden ist, können Sie dennoch manuell benutzerdefinierte Token erstellen. Zuerst findet einen Drittanbieter JWT Bibliothek für Ihre Sprache. Verwenden Sie dann diese JWT-Bibliothek, um ein JWT zu prägen, das die folgenden Ansprüche enthält:

Benutzerdefinierte Token-Ansprüche
alg Algorithmus "RS256"
iss Aussteller E-Mail-Adresse des Dienstkontos Ihres Projekts
sub Gegenstand E-Mail-Adresse des Dienstkontos Ihres Projekts
aud Publikum "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Ausgestellt-um-Zeit Die aktuelle Uhrzeit in Sekunden seit der UNIX-Epoche
exp Ablaufzeit Die Zeit in Sekunden seit der UNIX-Epoche, zu der das Token abläuft. Es kann ein Maximum von 3600 Sekunden später als der iat .
Hinweis: Dies steuert nur die Zeit , wenn die benutzerdefinierten Token selbst abläuft. Aber wenn Sie einen Benutzer melden Sie sich mit signInWithCustomToken() , werden sie in in das Gerät angemeldet bleiben , bis ihre Sitzung für ungültig erklärt wird oder der Benutzer abmeldet.
uid Die eindeutige Kennung des angemeldeten Benutzers muss eine Zeichenfolge mit einer Länge von 1-36 Zeichen sein
claims (optional) Optional individuelle Ansprüche in der Sicherheitsregeln schließen auth / request.auth Variablen

Hier sind einige Beispielimplementierungen zum Erstellen benutzerdefinierter Token in einer Vielzahl von Sprachen, die das Firebase Admin SDK nicht unterstützt:

PHP

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

Rubin

Mit 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

Nachdem Sie das benutzerdefinierte Token erstellt haben, senden Sie es zur Authentifizierung bei Firebase an Ihre Client-App. Sehen Sie sich die Codebeispiele oben an, um dies zu tun.

Fehlerbehebung

In diesem Abschnitt werden einige häufige Probleme beschrieben, auf die Entwickler beim Erstellen benutzerdefinierter Token stoßen können, und wie Sie diese beheben.

IAM-API nicht aktiviert

Wenn Sie eine Dienstkonto-ID zum Signieren von Token angeben, wird möglicherweise eine Fehlermeldung ähnlich der folgenden angezeigt:

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.

Das Firebase Admin SDK verwendet den IAM - API , um Zeichen Token. Dieser Fehler weist darauf hin, dass die IAM-API derzeit nicht für Ihr Firebase-Projekt aktiviert ist. Öffnen Sie den Link in der Fehlermeldung in einem Webbrowser und klicken Sie auf die Schaltfläche "API aktivieren", um sie für Ihr Projekt zu aktivieren.

Das Dienstkonto verfügt nicht über die erforderlichen Berechtigungen

Wenn der Dienst die Firebase Admin SDK - Konto ausgeführt wird , als nicht hat iam.serviceAccounts.signBlob Erlaubnis, wird möglicherweise eine Fehlermeldung wie die folgende erhalten:

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

Der einfachste Weg , dies zu lösen , ist die „Dienstkonto Token Creator“ IAM Rolle für das Dienstkonto in Frage zu erteilen, in der Regel {project-name}@appspot.gserviceaccount.com :

  1. Öffnen Sie die IAM und Admin - Seite in der Google Cloud Console.
  2. Wählen Sie Ihr Projekt aus und klicken Sie auf "Weiter".
  3. Klicken Sie auf das Bearbeitungssymbol, das dem Dienstkonto entspricht, das Sie aktualisieren möchten.
  4. Klicken Sie auf „Weitere Rolle hinzufügen“.
  5. Geben Sie "Service Account Token Creator" in den Suchfilter ein und wählen Sie ihn aus den Ergebnissen aus.
  6. Klicken Sie auf "Speichern", um die Rollenzuweisung zu bestätigen.

Siehe IAM - Dokumentation für weitere Details zu diesem Prozess, oder lernen , wie Update Rollen zu tun , um die gcloud Kommandozeilen - Tools.

Dienstkonto konnte nicht ermittelt werden

Wenn Sie eine Fehlermeldung ähnlich der folgenden erhalten, wurde das Firebase Admin SDK nicht richtig initialisiert.

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

Wenn Sie sich darauf verlassen, dass das SDK eine Dienstkonto-ID automatisch erkennt, stellen Sie sicher, dass der Code in einer verwalteten Google-Umgebung mit einem Metadatenserver bereitgestellt wird. Andernfalls müssen Sie bei der SDK-Initialisierung unbedingt die JSON-Datei oder die Dienstkonto-ID des Dienstkontos angeben.