Mit Firebase haben Sie die vollständige Kontrolle über die Authentifizierung, da Sie Folgendes tun können:
Nutzer oder Geräte mit sicheren JSON Web Tokens (JWTs) authentifizieren. Sie generieren
auf Ihrem Server, geben Sie sie
an ein Clientgerät zurück und verwenden
zur Authentifizierung mithilfe der Methode signInWithCustomToken()
.
Dazu müssen Sie einen Serverendpunkt erstellen, der die Anmeldung akzeptiert
Anmeldedaten wie Nutzername und Passwort und, falls diese Anmeldedaten
gültig ist, gibt ein benutzerdefiniertes JWT zurück. Das vom Server zurückgegebene benutzerdefinierte JWT kann dann
werden von einem Clientgerät zur Authentifizierung bei Firebase verwendet.
(iOS+, Android,
web). Nach der Authentifizierung wird diese Identität für den Zugriff auf andere Firebase-Dienste wie Firebase Realtime Database und Cloud Storage verwendet. Außerdem ist der Inhalt des JWT im auth
-Objekt in deiner Realtime Database Security Rules und im request.auth
-Objekt in deiner Cloud Storage Security Rules verfügbar.
Sie können ein benutzerdefiniertes Token mit dem Firebase Admin SDK erstellen oder Verwenden Sie die JWT-Bibliothek eines Drittanbieters, wenn Ihr Server eine Sprache, die Firebase nativ nicht unterstützt.
Hinweis
Benutzerdefinierte Tokens 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 Tokens verwendet werden soll:
- Mit einer Dienstkonto-JSON-Datei – Diese Methode kann in beliebigen Sie müssen jedoch eine JSON-Datei für das Dienstkonto verpacken. zusammen mit Ihrem Code. Es ist insbesondere darauf zu achten, Die JSON-Datei des Dienstkontos ist für externe Nutzer nicht zugänglich.
- Dienstkonto über das Admin SDK erkennen lassen -- Diese Methode können in von Google verwalteten Umgebungen wie Google Cloud verwendet werden. Functions und App Engine. Möglicherweise müssen Sie einige zusätzliche Berechtigungen über die Google Cloud-Konsole konfigurieren.
- Mit einer Dienstkonto-ID -- Bei Verwendung in einer von Google verwalteten Umgebung signiert diese Methode Tokens mit den Schlüssel des angegebenen Dienstkontos. Es wird jedoch ein Remote-Webdienst verwendet und Sie müssen möglicherweise zusätzliche Berechtigungen für dieses Dienstkonto über die Google Cloud-Konsole konfigurieren.
JSON-Datei für Dienstkonto verwenden
JSON-Dateien für Dienstkonten enthalten alle Informationen zu Dienstkonten, einschließlich des privaten RSA-Schlüssels. Sie können hier heruntergeladen werden: Firebase-Konsole. Weitere Informationen zum Initialisieren des Admin SDK mit einer JSON-Datei für ein Dienstkonto finden Sie in der Anleitung zum Einrichten des Admin SDK.
Diese Initialisierungsmethode eignet sich für eine Vielzahl von Admin SDK. Bereitstellungen. Außerdem ermöglicht es dem Admin SDK, benutzerdefinierte Tokens lokal zu erstellen und zu signieren, ohne Remote-API-Aufrufe auszuführen. Der größte Nachteil dieser Methode ist, Sie müssen eine JSON-Datei für das Dienstkonto verpacken, zusammen mit Ihrem Code. Der private Schlüssel in einem Dienstkonto Die JSON-Datei enthält vertrauliche Informationen. dass sie vertraulich behandelt werden. Insbesondere sollten Sie keine JSON-Dateien für Dienstkonten hinzufügen zur öffentlichen Versionskontrolle.
Dienstkonto mit dem Admin SDK erkennen lassen
Wenn Ihr Code in einer von Google verwalteten Umgebung bereitgestellt wird, gibt das Admin SDK kann versuchen, eine Methode zum Signieren benutzerdefinierter Tokens automatisch zu erkennen:
Wenn Ihr Code in der App Engine-Standardumgebung für Java, Python oder Go verwenden, kann das Admin SDK die Methode App Identity-Dienst in dieser Umgebung vorhanden ist, um benutzerdefinierte Tokens zu signieren. Der App Identity-Dienst signiert Daten mit einem Dienstkonto, das von der Google App Engine für Ihre App bereitgestellt wird.
Wenn Ihr Code in einer anderen verwalteten Umgebung bereitgestellt wird (z. B. Google Cloud Functions oder Google Compute Engine), kann das Firebase Admin SDK einen Dienstkonto-ID-String automatisch vom lokalen Metadatenserver ermitteln. Die ermittelte Dienstkonto-ID wird dann in Verbindung mit dem IAM-Dienst verwendet, um Tokens aus der Ferne zu signieren.
Damit du diese Signaturmethoden nutzen kannst, musst du das SDK mit Google initialisieren Standardanmeldedaten für Anwendungen und geben Sie keinen Dienstkonto-ID-String an:
Node.js
initializeApp();
Java
FirebaseApp.initializeApp();
Python
default_app = firebase_admin.initialize_app()
Go
app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
log.Fatalf("error initializing app: %v\n", err)
}
C#
FirebaseApp.Create();
Um denselben Code lokal zu testen, laden Sie eine Dienstkonto-JSON-Datei herunter und legen Sie
GOOGLE_APPLICATION_CREDENTIALS
, um darauf zu verweisen.
Wenn das Firebase Admin SDK einen Dienstkonto-ID-String erkennen muss, wenn mit Ihrem Code zum ersten Mal ein benutzerdefiniertes Token erstellt wird. Das Ergebnis wird im Cache gespeichert und für nachfolgende Tokensignaturvorgänge wiederverwendet. Die automatisch ermittelte Dienstkonto-ID ist in der Regel eines der Standarddienstkonten, die von der Google Cloud bereitgestellt werden:
Genau wie bei explizit angegebenen Dienstkonto-IDs müssen automatisch erkannte Dienstkonto-IDs die Berechtigung iam.serviceAccounts.signBlob
haben, damit die Erstellung benutzerdefinierter Tokens funktioniert. Möglicherweise müssen Sie den
Bereich IAM und Verwaltung
der Google Cloud-Konsole, um den Standarddienstkonten die Berechtigung
die erforderlichen Berechtigungen. Weitere Informationen finden Sie unten im Abschnitt zur Fehlerbehebung.
Dienstkonto-ID verwenden
Um für Konsistenz zwischen verschiedenen Teilen Ihrer Anwendung zu sorgen, können Sie eine Dienstkonto-ID angeben, deren Schlüssel zum Signieren von Tokens verwendet werden, wenn die Anwendung in einer von Google verwalteten Umgebung ausgeführt wird. Dadurch werden IAM-Richtlinien einfacher und sicherer Fügen Sie die JSON-Datei des Dienstkontos in Ihren Code ein.
Sie finden die Dienstkonto-ID in der Google Cloud-Konsole oder im Feld client_email
einer heruntergeladenen JSON-Datei für das Dienstkonto.
Dienstkonto-IDs sind E-Mail-Adressen im folgenden Format:
<client-id>@<project-id>.iam.gserviceaccount.com
. Sie dienen der eindeutigen Identifizierung von Dienstkonten in Firebase- und Google Cloud-Projekten.
Wenn du benutzerdefinierte Tokens mit einer separaten Dienstkonto-ID erstellen möchtest, initialisieren Sie das SDK wie unten dargestellt:
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)
Go
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 sind daher nicht öffentlich sichtbar
sind unbedeutend. Um jedoch benutzerdefinierte Tokens mit dem angegebenen Dienst zu signieren,
Konto enthält, muss das Firebase Admin SDK einen Remote-Dienst aufrufen.
Außerdem muss das Dienstkonto, das vom Admin SDK für diesen Aufruf verwendet wird (normalerweise {project-name}@appspot.gserviceaccount.com
), die Berechtigung iam.serviceAccounts.signBlob
haben.
Weitere Informationen finden Sie unten im Abschnitt zur Fehlerbehebung.
Benutzerdefinierte Tokens mit dem Firebase Admin SDK erstellen
Das Firebase Admin SDK verfügt über eine integrierte Methode zum Erstellen benutzerdefinierter Tokens. Sie müssen mindestens eine uid
angeben. Dies kann ein beliebiger String sein, der den Nutzer oder das Gerät, das Sie authentifizieren, eindeutig identifiziert. Diese Tokens laufen ab
nach einer Stunde.
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)
Go
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 Anforderungen angeben, die in den benutzerdefinierten
Token. Im folgenden Beispiel wurde dem benutzerdefinierten Token beispielsweise ein premiumAccount
-Feld hinzugefügt, das in den auth
-/request.auth
-Objekten in Ihren Sicherheitsregeln verfügbar ist:
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)
Go
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
Reservierte benutzerdefinierte Tokennamen
Anmeldung mit benutzerdefinierten Tokens auf Clients
Nachdem Sie ein benutzerdefiniertes Token erstellt haben, sollten Sie es an Ihre Clientanwendung senden. Die Clientanwendung authentifiziert sich mit dem benutzerdefinierten Token, indem sie signInWithCustomToken()
aufruft:
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);
}
}
});
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.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;
// ...
});
Wenn die Authentifizierung erfolgreich war, wird der Nutzer jetzt in Ihrem
Client-App mit dem in der uid
angegebenen Konto im benutzerdefinierten
Token. Wenn das Konto noch nicht vorhanden war, wird ein Eintrag für diesen Nutzer erstellt.
erstellt.
Wie bei anderen Anmeldemethoden (z. B. signInWithEmailAndPassword()
und signInWithCredential()
) werden das auth
-Objekt in Realtime Database Security Rules und das request.auth
-Objekt in Cloud Storage Security Rules mit der uid
des Nutzers ausgefüllt. In diesem Fall ist uid
der Wert,
die Sie beim Generieren des benutzerdefinierten Tokens angegeben haben.
Datenbankregeln
{
"rules": {
"adminContent": {
".read": "auth.uid === 'some-uid'"
}
}
}
Speicherregeln
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 auf das Objekt auth.token
(Firebase Realtime Database) oder request.auth.token
(Cloud Storage) in Ihren Regeln verwiesen werden:
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;
}
}
}
Benutzerdefinierte Tokens mithilfe der JWT-Bibliothek eines Drittanbieters erstellen
Wenn Ihr Back-End in einer Sprache geschrieben ist, für die es kein offizielles Firebase Admin SDK gibt, können Sie trotzdem benutzerdefinierte Tokens manuell erstellen. Suchen Sie zuerst nach einer JWT-Bibliothek eines Drittanbieters für Ihre Sprache. Verwenden Sie dann diese JWT-Bibliothek erstellen, um ein JWT mit den folgenden Anforderungen zu erstellen:
Anforderungen an benutzerdefinierte Tokens | ||
---|---|---|
alg |
Algorithmus | "RS256" |
iss |
Aussteller | Die E-Mail-Adresse des Dienstkontos Ihres Projekts |
sub |
Betreff | E-Mail-Adresse des Dienstkontos Ihres Projekts |
aud |
Zielgruppe | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Ausstellungszeit | Die aktuelle Zeit in Sekunden seit der UNIX-Epoche |
exp |
Ablaufzeit |
Die Zeit in Sekunden seit der UNIX-Epoche, zu der das Token abläuft. Dies kann maximal 3.600 Sekunden später als iat sein.
Beachten Sie, dass damit nur der Zeitpunkt gesteuert wird, zu dem das benutzerdefinierte Token selbst abläuft. Wenn Sie jedoch einen Nutzer mit signInWithCustomToken() anmelden, bleiben er so lange auf dem Gerät angemeldet, bis die Sitzung ungültig wird oder der Nutzer sich abmeldet.
|
uid |
Die eindeutige Kennung des angemeldeten Nutzers muss ein String sein, der zwischen
1–128 Zeichen (einschließlich). Kürzere uid s bieten bessere
die Leistung.
|
|
claims (optional) |
Optionale benutzerdefinierte Anforderungen, die in die Variablen auth /request.auth der Sicherheitsregeln aufgenommen werden sollen
|
Hier sind einige Implementierungsbeispiele für die Erstellung von benutzerdefinierten Tokens in einem Sprachen, die vom Firebase Admin SDK nicht unterstützt werden:
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");
}
Ruby
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 Verwendung an die Client-App. sich bei Firebase zu authentifizieren. Weitere Informationen finden Sie in den Codebeispielen oben.
Fehlerbehebung
In diesem Abschnitt werden einige häufige Probleme beschrieben, auf die Entwickler beim Erstellen benutzerdefinierter Tokens und wie Sie diese auflösen.
IAM API nicht aktiviert
Wenn Sie eine Dienstkonto-ID für die Signatur von Tokens angeben, erhalten Sie möglicherweise einen ähnlichen Fehler wie den folgenden:
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 die IAM API um Tokens zu signieren. Dieser Fehler weist darauf hin, dass die IAM API derzeit nicht aktiviert ist für dein Firebase-Projekt Ö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 hat nicht die erforderlichen Berechtigungen
Wenn das Dienstkonto, unter dem das Firebase Admin SDK ausgeführt wird, nicht die Berechtigung iam.serviceAccounts.signBlob
hat, wird möglicherweise eine Fehlermeldung wie die folgende angezeigt:
Permission iam.serviceAccounts.signBlob is required to perform this operation on service account projects/-/serviceAccounts/{your-service-account-id}.
Am einfachsten lässt sich das Problem beheben, indem Sie dem betreffenden Dienstkonto die IAM-Rolle „Ersteller von Dienstkonto-Tokens“ zuweisen, in der Regel {project-name}@appspot.gserviceaccount.com
:
- Öffnen Sie in der Google Cloud Console die Seite IAM und Verwaltung.
- Wählen Sie Ihr Projekt aus und klicken Sie auf „Weiter“.
- Klicken Sie auf das Bearbeitungssymbol für das Dienstkonto, das Sie aktualisieren möchten.
- Klicken Sie auf „Weitere Rolle hinzufügen“.
- Geben Sie „Ersteller von Dienstkonto-Tokens“ in den Suchfilter ein und wählen Sie die Option aus den Ergebnissen aus.
- Klicken Sie auf „Speichern“, um die Rollenzuweisung zu bestätigen.
Weitere Informationen zu diesem Vorgang finden Sie in der IAM-Dokumentation. Dort erfahren Sie auch, wie Sie Rollen mit dem gcloud-Befehlszeilentool aktualisieren.
Dienstkonto konnte nicht ermittelt werden
Wenn Sie eine Fehlermeldung wie die folgende 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 die automatische Erkennung einer Dienstkonto-ID vom SDK nutzen, wird der Code in einer verwalteten Google-Umgebung mit einem Metadatenserver bereitgestellt. Andernfalls müssen Sie bei der SDK-Initialisierung die JSON-Datei des Dienstkontos oder die Dienstkonto-ID angeben.