Google 致力于为黑人社区推动种族平等。查看具体举措

Créer des jetons personnalisés

Firebase vous donne un contrôle total sur l'authentification en vous permettant d'authentifier les utilisateurs ou les appareils à l'aide de jetons Web JSON (JWT) sécurisés. Vous générez ces jetons sur votre serveur, les transmettre à un équipement client, puis les utiliser pour authentifier via le signInWithCustomToken() méthode.

Pour ce faire, vous devez créer un point de terminaison de serveur qui accepte les informations d'identification de connexion, telles qu'un nom d'utilisateur et un mot de passe, et, si les informations d'identification sont valides, renvoie un JWT personnalisé. Le JWT personnalisé retourné de votre serveur peut ensuite être utilisé par un dispositif client pour authentifier avec Firebase ( iOS , Android , Web ). Une fois authentifiée, cette identité sera utilisée lors de l'accès à d'autres services Firebase, tels que Firebase Realtime Database et Cloud Storage. En outre, le contenu du JWT seront disponibles dans le auth objet dans vos règles de base de données en request.auth temps réel et l' request.auth objet dans vos règles de sécurité Cloud Storage .

Vous pouvez créer un jeton personnalisé avec le SDK Firebase Admin ou utiliser une bibliothèque JWT tierce si votre serveur est écrit dans une langue que Firebase ne prend pas en charge de manière native.

Avant que tu commences

Les jetons personnalisés sont des JWT signés où la clé privée utilisée pour la signature appartient à un compte de service Google. Il existe plusieurs manières de spécifier le compte de service Google qui doit être utilisé par le SDK Firebase Admin pour signer des jetons personnalisés :

  • L' utilisation d' un compte de service fichier JSON - Cette méthode peut être utilisée dans un environnement, mais vous oblige à emballer un compte de service fichier JSON avec votre code. Des précautions particulières doivent être prises pour s'assurer que le fichier JSON du compte de service n'est pas exposé à des parties externes.
  • Laisser le Admin SDK découvrir un compte de service - Cette méthode peut être utilisée dans des environnements gérés par Google telles que les fonctions Google Cloud et App Engine. Vous devrez peut-être configurer des autorisations supplémentaires via Google Cloud Console.
  • L' utilisation d' un numéro de compte de service - Lorsqu'il est utilisé dans un environnement géré par Google cette méthode signera des jetons en utilisant la clé du compte de service spécifié. Cependant, il utilise un service Web distant et vous devrez peut-être configurer des autorisations supplémentaires pour ce compte de service via Google Cloud Console.

Utilisation d'un fichier JSON de compte de service

Les fichiers JSON de compte de service contiennent toutes les informations correspondant aux comptes de service (y compris la clé privée RSA). Ils peuvent être téléchargés depuis la console Firebase. Suivez le Admin SDK mis en place des instructions pour plus d' informations sur la façon d'initialiser le Admin SDK avec un compte de service fichier JSON.

Cette méthode d'initialisation convient à un large éventail de déploiements de SDK Admin. Il permet également au SDK Admin de créer et de signer des jetons personnalisés localement, sans effectuer d'appels d'API à distance. Le principal inconvénient de cette approche est qu'elle vous oblige à empaqueter un fichier JSON de compte de service avec votre code. Notez également que la clé privée dans un fichier JSON de compte de service est une information sensible et qu'une attention particulière doit être portée pour la garder confidentielle. Plus précisément, évitez d'ajouter des fichiers JSON de compte de service au contrôle de version public.

Laisser le SDK Admin découvrir un compte de service

Si votre code est déployé dans un environnement géré par Google, le SDK Admin peut tenter de découvrir automatiquement un moyen de signer des jetons personnalisés :

  • Si votre code est déployé dans l'environnement standard App Engine pour Java, Python ou Go, le SDK Admin peut utiliser le service de l' identité App présente dans cet environnement pour signer des jetons personnalisés. Le service App Identity signe les données à l'aide d'un compte de service fourni pour votre application par Google App Engine.

  • Si votre code est déployé dans un autre environnement géré (par exemple fonctions Google Cloud, Google Compute Engine), le Firebase Administrateur SDK peut découvrir automatiquement une chaîne d'identification de compte de service du local serveur de métadonnées . L'ID de compte de service découvert est ensuite utilisé avec le service IAM pour signer des jetons à distance.

Pour utiliser ces méthodes de signature, initialisez le SDK avec les identifiants par défaut de l'application Google et ne spécifiez pas de chaîne d'ID de compte de service :

Node.js

admin.initializeApp();

Java

FirebaseApp.initializeApp();

Python

default_app = firebase_admin.initialize_app()

Aller

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

C#

FirebaseApp.Create();

Pour tester le même code localement, téléchargez un compte de service fichier JSON et définissez la GOOGLE_APPLICATION_CREDENTIALS variable d'environnement pour pointer vers elle.

Si le SDK Firebase Admin doit découvrir une chaîne d'ID de compte de service, il le fait lorsque votre code crée un jeton personnalisé pour la première fois. Le résultat est mis en cache et réutilisé pour les opérations de signature de jeton suivantes. L'ID de compte de service détecté automatiquement est généralement l'un des comptes de service par défaut fournis par Google Cloud :

Tout comme avec les ID de compte de service explicitement spécifié, ID de compte de service d' auto-découvert doivent avoir la iam.serviceAccounts.signBlob autorisation pour la création de jeton personnalisé au travail. Vous devrez peut-être utiliser l' IAM et administrateur section du Google Cloud Console d'accorder le service par défaut des comptes , les autorisations nécessaires. Voir la section de dépannage ci-dessous pour plus de détails.

Utilisation d'un identifiant de compte de service

Pour maintenir la cohérence entre les différentes parties de votre application, vous pouvez spécifier un ID de compte de service dont les clés seront utilisées pour signer les jetons lors de l'exécution dans un environnement géré par Google. Cela peut rendre les stratégies IAM plus simples et plus sécurisées, et éviter d'avoir à inclure le fichier JSON du compte de service dans votre code.

L'ID de compte de service se trouve dans le Google Cloud Console , ou dans le client_email champ d'un fichier JSON compte de service téléchargé. ID de compte de service sont des adresses e - mail qui ont le format suivant: <client-id>@<project-id>.iam.gserviceaccount.com . Ils identifient de manière unique les comptes de service dans les projets Firebase et Google Cloud.

Pour créer des jetons personnalisés à l'aide d'un ID de compte de service distinct, initialisez le SDK comme indiqué ci-dessous :

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)

Aller

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

Les identifiants de compte de service ne sont pas des informations sensibles et leur exposition est donc sans conséquence. Cependant, pour signer des jetons personnalisés avec le compte de service spécifié, le SDK Firebase Admin doit appeler un service distant. De plus, vous devez également vous assurer que le service compte le SDK Admin utilise pour faire cet appel -généralement {project-name}@appspot.gserviceaccount.com - a la iam.serviceAccounts.signBlob permission . Voir la section de dépannage ci-dessous pour plus de détails.

Créer des jetons personnalisés à l'aide du SDK Firebase Admin

Le SDK Firebase Admin dispose d'une méthode intégrée pour créer des jetons personnalisés. Au minimum, vous devez fournir un uid , qui peut être une chaîne mais doit identifier de manière unique l'utilisateur ou périphérique que vous authentifiez. Ces jetons expirent après une heure.

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)

Aller

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

Vous pouvez également éventuellement spécifier des revendications supplémentaires à inclure dans le jeton personnalisé. Par exemple, ci - dessous, un premiumAccount champ a été ajouté au jeton personnalisé, qui sera disponible dans les auth / request.auth objets dans vos règles de sécurité:

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)

Aller

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

Connectez-vous à l'aide de jetons personnalisés sur les clients

Après avoir créé un jeton personnalisé, vous devez l'envoyer à votre application cliente. L'application client authentifie avec la coutume jeton en appelant signInWithCustomToken() :

iOS

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

Unité

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

la toile

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

Si l'authentification réussit, votre utilisateur sera maintenant signé dans votre application client avec le compte indiqué par le uid inclus dans le jeton personnalisé. Si ce compte n'existait pas auparavant, un enregistrement pour cet utilisateur sera créé.

De la même manière que d'autres signes dans les méthodes (telles que signInWithEmailAndPassword() et signInWithCredential() ) l' auth objet dans vos règles de base de données en request.auth uid temps réel et l' request.auth objet dans vos règles de sécurité Cloud Storage seront renseignés avec l'utilisateur uid . Dans ce cas, le uid sera celui que vous avez spécifié lors de la génération du jeton personnalisé.

Règles de base de données

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

Règles de stockage

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

Si le jeton personnalisé contient des revendications supplémentaires, ils peuvent être référencés hors de la auth.token (Firebase en temps réel Base de données) ou request.auth.token objet (Cloud Storage) dans vos règles:

Règles de base de données

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

Règles de stockage

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

Créer des jetons personnalisés à l'aide d'une bibliothèque JWT tierce

Si votre backend est dans une langue qui n'a pas de SDK Firebase Admin officiel, vous pouvez toujours créer manuellement des jetons personnalisés. Tout d' abord, trouver une bibliothèque de JWT tiers pour votre langue. Ensuite, utilisez cette bibliothèque JWT pour créer un JWT qui inclut les revendications suivantes :

Revendications de jetons personnalisés
alg Algorithme "RS256"
iss Émetteur L'adresse e-mail du compte de service de votre projet
sub Sujet L'adresse e-mail du compte de service de votre projet
aud Public "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Émis à l'heure L'heure actuelle, en secondes depuis l'époque UNIX
exp Date d'expiration L'heure, en secondes, depuis l'époque UNIX, à laquelle le jeton expire. Il peut être un maximum de 3600 secondes plus tard que le iat .
Remarque: ce ne contrôle que le moment où la coutume jeton lui - même arrive à expiration. Mais une fois que vous signez un utilisateur à l' aide signInWithCustomToken() , ils resteront signé dans l'appareil jusqu'à sa session est invalidée ou les utilisateur se déconnecte.
uid L'identifiant unique de l'utilisateur connecté doit être une chaîne de 1 à 36 caractères
claims (facultatif) Revendications personnalisées en option à inclure dans les règles de sécurité auth / request.auth les variables

Voici quelques exemples de mise en œuvre de la création de jetons personnalisés dans diverses langues que le SDK Admin Firebase ne prend pas en charge :

PHP

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

Rubis

En utilisant 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

Après avoir créé le jeton personnalisé, envoyez-le à votre application cliente pour l'utiliser pour vous authentifier auprès de Firebase. Consultez les exemples de code ci-dessus pour savoir comment procéder.

Dépannage

Cette section décrit certains problèmes courants que les développeurs peuvent rencontrer lors de la création de jetons personnalisés et comment les résoudre.

API IAM non activée

Si vous spécifiez un ID de compte de service pour la signature de jetons, vous pouvez obtenir une erreur semblable à la suivante :

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.

Le SDK Firebase administrateur utilise l' API IAM aux jetons de signe. Cette erreur indique que l'API IAM n'est actuellement pas activée pour votre projet Firebase. Ouvrez le lien dans le message d'erreur dans un navigateur Web et cliquez sur le bouton "Activer l'API" pour l'activer pour votre projet.

Le compte de service n'a pas les autorisations requises

Si le service compte le Firebase Administrateur SDK fonctionne comme ne pas la iam.serviceAccounts.signBlob permission, vous pouvez obtenir un message d'erreur comme suit:

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

La meilleure façon de résoudre c'est d'accorder le rôle de IAM « compte de service de jeton Créateur » pour le compte de service en question, généralement {project-name}@appspot.gserviceaccount.com :

  1. Ouvrez l' IAM et admin page dans le Google Cloud Console.
  2. Sélectionnez votre projet et cliquez sur "Continuer".
  3. Cliquez sur l'icône de modification correspondant au compte de service que vous souhaitez mettre à jour.
  4. Cliquez sur "Ajouter un autre rôle".
  5. Tapez « Service Account Token Creator » dans le filtre de recherche et sélectionnez-le dans les résultats.
  6. Cliquez sur "Enregistrer" pour confirmer l'attribution du rôle.

Reportez - vous à la documentation IAM pour plus de détails sur ce processus, ou apprendre à faire des rôles de mise à jour à l' aide des outils de ligne de commande gcloud.

Échec de la détermination du compte de service

Si vous obtenez un message d'erreur semblable au suivant, le SDK Firebase Admin n'a pas été correctement initialisé.

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

Si vous comptez sur le SDK pour découvrir automatiquement un ID de compte de service, assurez-vous que le code est déployé dans un environnement Google géré avec un serveur de métadonnées. Sinon, assurez-vous de spécifier le fichier JSON du compte de service ou l'ID du compte de service lors de l'initialisation du SDK.