Catch up on everthing we announced at this year's Firebase Summit. Learn more

Crea token personalizzati

Firebase ti offre il controllo completo sull'autenticazione consentendoti di autenticare utenti o dispositivi utilizzando JSON Web Token (JWT) sicuri. Si generano questi token sul server, li passa di nuovo ad un dispositivo client, e poi li utilizzano per l'autenticazione tramite il signInWithCustomToken() metodo.

Per ottenere ciò, è necessario creare un endpoint server che accetti le credenziali di accesso, ad esempio nome utente e password, e, se le credenziali sono valide, restituisce un JWT personalizzato. Il JWT personalizzato restituita dal server può quindi essere utilizzato da un dispositivo client per l'autenticazione con Firebase ( iOS + , Android , web ). Una volta autenticata, questa identità verrà utilizzata per l'accesso ad altri servizi Firebase, come Firebase Realtime Database e Cloud Storage. Inoltre, i contenuti del JWT saranno disponibili nel auth oggetto nel Regole base di dati in tempo reale e l' request.auth oggetto nel bagagli Regole di sicurezza cloud .

Puoi creare un token personalizzato con Firebase Admin SDK oppure puoi utilizzare una libreria JWT di terze parti se il tuo server è scritto in una lingua che Firebase non supporta in modo nativo.

Prima di iniziare

I token personalizzati sono JWT firmati in cui la chiave privata utilizzata per la firma appartiene a un account di servizio Google. Esistono diversi modi per specificare l'account del servizio Google che deve essere utilizzato da Firebase Admin SDK per la firma di token personalizzati:

  • Utilizzo di un file JSON account di servizio - Questo metodo può essere utilizzato in qualsiasi ambiente, ma si richiede per confezionare un file JSON account di servizio con il vostro codice. È necessario prestare particolare attenzione per garantire che il file JSON dell'account di servizio non sia esposto a parti esterne.
  • Lasciando l'SDK Admin scoprire un account di servizio - Questo metodo può essere utilizzato in ambienti gestiti da Google, come le funzioni di Google Cloud e App Engine. Potrebbe essere necessario configurare alcune autorizzazioni aggiuntive tramite Google Cloud Console.
  • Utilizzando un ID account di servizio - Quando utilizzato in un ambiente di Google gestiti questo metodo firmerà i token utilizzando il tasto di account di servizio specificato. Tuttavia, utilizza un servizio Web remoto e potrebbe essere necessario configurare autorizzazioni aggiuntive per questo account di servizio tramite Google Cloud Console.

Utilizzo di un file JSON dell'account di servizio

I file JSON dell'account di servizio contengono tutte le informazioni corrispondenti agli account di servizio (inclusa la chiave privata RSA). Possono essere scaricati dalla console Firebase. Seguire la SDK di amministrazione istituito istruzioni per ulteriori informazioni su come inizializzare l'Admin SDK con un file JSON account di servizio.

Questo metodo di inizializzazione è adatto per un'ampia gamma di distribuzioni di SDK Admin. Inoltre, consente all'Admin SDK di creare e firmare token personalizzati localmente, senza effettuare chiamate API remote. Lo svantaggio principale di questo approccio è che richiede di impacchettare un file JSON dell'account di servizio insieme al codice. Si noti inoltre che la chiave privata in un file JSON dell'account di servizio è un'informazione sensibile e occorre prestare particolare attenzione per mantenerla riservata. In particolare, evita di aggiungere file JSON dell'account di servizio al controllo della versione pubblica.

Consentire all'Admin SDK di scoprire un account di servizio

Se il tuo codice viene distribuito in un ambiente gestito da Google, Admin SDK può tentare di individuare automaticamente un mezzo per firmare token personalizzati:

  • Se il codice viene distribuito in un ambiente standard di App Engine per Java, Python o Go, l'SDK Admin può utilizzare il servizio di App identità presenti in tale ambiente per firmare i token personalizzati. Il servizio App Identity firma i dati utilizzando un account di servizio fornito per la tua app da Google App Engine.

  • Se il codice viene distribuito in qualche altro ambiente gestito (ad esempio le funzioni di Google Cloud, Google Compute Engine), la lattina Firebase Admin SDK auto-scoperta di una stringa di ID account di servizio dal locale server di metadati . L'ID account di servizio rilevato viene quindi utilizzato insieme al servizio IAM per firmare i token in remoto.

Per utilizzare questi metodi di firma, inizializza l'SDK con le credenziali predefinite dell'applicazione Google e non specificare una stringa ID dell'account di servizio:

Nodo.js

initializeApp();

Giava

FirebaseApp.initializeApp();

Pitone

default_app = firebase_admin.initialize_app()

andare

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

C#

FirebaseApp.Create();

Per provare lo stesso codice a livello locale, scaricare un file JSON account di servizio e impostare la GOOGLE_APPLICATION_CREDENTIALS variabile d'ambiente a punto ad esso.

Se Firebase Admin SDK deve rilevare una stringa ID dell'account di servizio, lo fa quando il codice crea un token personalizzato per la prima volta. Il risultato viene memorizzato nella cache e riutilizzato per le successive operazioni di firma del token. L'ID account di servizio rilevato automaticamente è in genere uno degli account di servizio predefiniti forniti da Google Cloud:

Proprio come con ID account di servizio esplicitamente specificati, ID account di servizio auto-scoperto devono avere iam.serviceAccounts.signBlob permesso per la creazione token personalizzato al lavoro. Potrebbe essere necessario utilizzare l'IAM e admin sezione del Google Cloud Console di concedere gli account di servizio predefinito delle autorizzazioni necessarie. Vedere la sezione sulla risoluzione dei problemi di seguito per maggiori dettagli.

Utilizzo di un ID account di servizio

Per mantenere la coerenza tra le varie parti della tua applicazione, puoi specificare un ID account di servizio le cui chiavi verranno utilizzate per firmare i token durante l'esecuzione in un ambiente gestito da Google. Ciò può rendere le policy IAM più semplici e sicure ed evitare di dover includere il file JSON dell'account di servizio nel codice.

L'ID account di servizio può essere trovato nel Google Cloud Console , o nel client_email campo di un file di account di servizio JSON scaricato. ID account di servizio sono indirizzi di posta elettronica che hanno il formato seguente: <client-id>@<project-id>.iam.gserviceaccount.com . Identificano in modo univoco gli account di servizio nei progetti Firebase e Google Cloud.

Per creare token personalizzati utilizzando un ID account di servizio separato, inizializza l'SDK come mostrato di seguito:

Nodo.js

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

Giava

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

Pitone

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

andare

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

Gli ID dell'account di servizio non sono informazioni riservate e pertanto la loro esposizione è irrilevante. Tuttavia, per firmare token personalizzati con l'account di servizio specificato, Firebase Admin SDK deve richiamare un servizio remoto. Inoltre, si deve anche fare in modo che il servizio l'account SDK Admin sta usando per effettuare questa chiamata -di solito {project-name}@appspot.gserviceaccount.com - ha iam.serviceAccounts.signBlob autorizzazione . Vedere la sezione sulla risoluzione dei problemi di seguito per maggiori dettagli.

Crea token personalizzati utilizzando Firebase Admin SDK

Firebase Admin SDK ha un metodo integrato per la creazione di token personalizzati. Come minimo, è necessario fornire un uid , che può essere qualsiasi stringa, ma dovrebbe identificare in modo univoco l'utente o il dispositivo si esegue l'autenticazione. Questi token scadono dopo un'ora.

Nodo.js

const uid = 'some-uid';

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

Giava

String uid = "some-uid";

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

Pitone

uid = 'some-uid'

custom_token = auth.create_custom_token(uid)

andare

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

È inoltre possibile specificare ulteriori attestazioni da includere nel token personalizzato. Ad esempio, di seguito, un premiumAccount campo è stato aggiunto al token personalizzato, che sarà disponibile nelle auth / request.auth oggetti nelle regole di sicurezza:

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

Giava

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

Pitone

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

custom_token = auth.create_custom_token(uid, additional_claims)

andare

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

Nomi token personalizzati riservati

Accedi utilizzando token personalizzati sui client

Dopo aver creato un token personalizzato, dovresti inviarlo alla tua app client. I autentica client App con l'usanza Token chiamando signInWithCustomToken() :

iOS+

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

ragnatela

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

Se l'autenticazione ha esito positivo, l'utente verrà ora firmato nella vostra applicazione client con il conto indicato dal uid incluso nel token personalizzato. Se quell'account non esisteva in precedenza, verrà creato un record per quell'utente.

Allo stesso modo come con altro segno-in metodi (come ad esempio signInWithEmailAndPassword() e signInWithCredential() ) l' auth oggetto nel Regole base di dati in tempo reale e l' request.auth oggetto nel Sicurezza Regole Cloud Storage verranno popolati con l'utente uid . In questo caso, l' uid sarà quello che si è specificato quando si genera il token personalizzato.

Regole del database

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

Regole di archiviazione

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

Se il token personalizzato contiene ulteriori rivendicazioni, che è possibile fare riferimento al largo della auth.token (Firebase in tempo reale di database) o request.auth.token (Cloud Storage) oggetto nelle regole:

Regole del database

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

Regole di archiviazione

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

Crea token personalizzati utilizzando una libreria JWT di terze parti

Se il tuo backend è in una lingua che non dispone di un Firebase Admin SDK ufficiale, puoi comunque creare manualmente token personalizzati. In primo luogo, trovare una libreria JWT di terze parti per la propria lingua. Quindi, usa quella libreria JWT per coniare un JWT che include le seguenti affermazioni:

Reclami di token personalizzati
alg Algoritmo "RS256"
iss Emittente Indirizzo email dell'account di servizio del tuo progetto
sub Soggetto Indirizzo email dell'account di servizio del tuo progetto
aud Pubblico "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Rilasciato al momento L'ora corrente, in secondi dall'epoca UNIX
exp Data di scadenza L'ora, in secondi dall'epoca UNIX, alla quale scade il token. Può essere un massimo di 3600 secondi più tardi iat .
Nota: questo controlla solo il momento in cui l'usanza del token stesso scade. Ma una volta che firmare un utente nell'utilizzo signInWithCustomToken() , che resterà firmato nel nel dispositivo fino alla loro sessione è invalidato o l'utente segni fuori.
uid L'identificatore univoco dell'utente che ha effettuato l'accesso deve essere una stringa di lunghezza compresa tra 1 e 36 caratteri
claims (opzionale) Attestazioni personalizzate opzionali da includere nelle regole di sicurezza auth / request.auth variabili

Di seguito sono riportati alcuni esempi di implementazione di come creare token personalizzati in una varietà di lingue non supportate da Firebase Admin SDK:

PHP

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

Rubino

Utilizzando 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

Dopo aver creato il token personalizzato, invialo all'app client da utilizzare per l'autenticazione con Firebase. Vedere gli esempi di codice sopra per come eseguire questa operazione.

Risoluzione dei problemi

Questa sezione descrive alcuni problemi comuni che gli sviluppatori possono incontrare durante la creazione di token personalizzati e come risolverli.

API IAM non abilitata

Se stai specificando un ID account di servizio per la firma dei token, potresti ricevere un errore simile al seguente:

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.

Il Firebase Admin SDK utilizza l' API IAM a gettoni segno. Questo errore indica che l'API IAM non è attualmente abilitata per il tuo progetto Firebase. Apri il link nel messaggio di errore in un browser web e fai clic sul pulsante "Abilita API" per abilitarlo per il tuo progetto.

L'account di servizio non dispone delle autorizzazioni necessarie

Se il servizio l'account Firebase Admin SDK è in esecuzione come non ha iam.serviceAccounts.signBlob autorizzazione, è possibile ottenere un messaggio di errore simile al seguente:

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

Il modo più semplice per risolvere questo è quello di concedere il "Servizio Account Token Creatore" ruolo IAM per l'account del servizio in questione, di solito {project-name}@appspot.gserviceaccount.com :

  1. Aprire l'IAM e admin pagina del Google Cloud Console.
  2. Seleziona il tuo progetto e fai clic su "Continua".
  3. Fare clic sull'icona di modifica corrispondente all'account del servizio che si desidera aggiornare.
  4. Fare clic su "Aggiungi un altro ruolo".
  5. Digita "Service Account Token Creator" nel filtro di ricerca e selezionalo dai risultati.
  6. Fare clic su "Salva" per confermare la concessione del ruolo.

Fare riferimento alla documentazione di IAM per maggiori dettagli su questo processo, o imparare a fare i ruoli di aggiornamento utilizzando gli strumenti della riga di comando gcloud.

Impossibile determinare l'account di servizio

Se ricevi un messaggio di errore simile al seguente, Firebase Admin SDK non è stato inizializzato correttamente.

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

Se ti affidi all'SDK per rilevare automaticamente un ID account di servizio, assicurati che il codice sia distribuito in un ambiente Google gestito con un server di metadati. In caso contrario, assicurati di specificare il file JSON dell'account di servizio o l'ID dell'account di servizio durante l'inizializzazione dell'SDK.