Google is committed to advancing racial equity for Black communities. See how.
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Crea token personalizzati

Firebase ti offre il controllo completo sull'autenticazione consentendoti di autenticare utenti o dispositivi utilizzando token Web JSON (JWT) sicuri. Questi token vengono generati sul server, vengono restituiti a un dispositivo client e quindi utilizzati per l'autenticazione tramite il metodo signInWithCustomToken() .

Per ottenere ciò, è necessario creare un endpoint server che accetti le credenziali di accesso, ad esempio un nome utente e una password, e, se le credenziali sono valide, restituisca un JWT personalizzato. Il JWT personalizzato restituito dal tuo server può quindi essere utilizzato da un dispositivo client per l'autenticazione con Firebase ( iOS , Android , web ). Una volta autenticata, questa identità verrà utilizzata quando si accede ad altri servizi Firebase, come Firebase Realtime Database e Cloud Storage. Inoltre, il contenuto del JWT sarà disponibile nell'oggetto di auth nelle regole del database in tempo reale e nell'oggetto request.auth nelle regole di sicurezza del cloud storage .

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 di servizio Google che deve essere utilizzato da Firebase Admin SDK per la firma di token personalizzati:

  • Utilizzo di un file JSON dell'account di servizio : questo metodo può essere utilizzato in qualsiasi ambiente, ma richiede di creare un pacchetto di un file JSON dell'account di servizio insieme al codice. È necessario prestare particolare attenzione per garantire che il file JSON dell'account di servizio non sia esposto a parti esterne.
  • Consentire all'Admin SDK di rilevare un account di servizio : questo metodo può essere utilizzato in ambienti gestiti da Google come Google Cloud Functions e App Engine. Potrebbe essere necessario configurare alcune autorizzazioni aggiuntive tramite Google Cloud Console.
  • Utilizzo di un ID account di servizio : se utilizzato in un ambiente gestito da Google, questo metodo firmerà i token utilizzando la chiave dell'account di servizio specificato. Tuttavia, utilizza un servizio Web remoto e potresti dover 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. Segui le istruzioni di configurazione dell'Admin SDK per ulteriori informazioni su come inizializzare l'Admin SDK con un file JSON dell'account di servizio.

Questo metodo di inizializzazione è adatto per un'ampia gamma di distribuzioni di SDK di amministrazione. Inoltre, consente all'Admin SDK di creare e firmare token personalizzati in locale, senza effettuare chiamate API remote. Lo svantaggio principale di questo approccio è che richiede di creare un pacchetto di 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 che è necessario 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 rilevare un account di servizio

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

  • Se il codice viene distribuito nell'ambiente standard di App Engine per Java, Python o Go, Admin SDK può utilizzare il servizio App Identity presente in quell'ambiente per firmare 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 un altro ambiente gestito (ad es. Google Cloud Functions, Google Compute Engine), Firebase Admin SDK può rilevare automaticamente una stringa ID account di servizio dal server di metadati locale. L'ID dell'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 account di servizio:

Node.js

admin.initializeApp();

Giava

FirebaseApp.initializeApp();

Pitone

default_app = firebase_admin.initialize_app()

Partire

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

C #

FirebaseApp.Create();

Per testare lo stesso codice in locale, scarica un file JSON dell'account di servizio e imposta la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS in modo che punti ad esso.

Se Firebase Admin SDK deve rilevare una stringa ID 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 è solitamente uno degli account di servizio predefiniti forniti da Google Cloud:

Proprio come con gli ID account di servizio specificati in modo esplicito, gli ID account di servizio a rilevamento automatico devono disporre dell'autorizzazione iam.serviceAccounts.signBlob affinché la creazione del token personalizzato funzioni. Potrebbe essere necessario utilizzare la sezione IAM e amministrazione di Google Cloud Console per concedere agli account di servizio predefiniti le autorizzazioni necessarie. Vedere la sezione di risoluzione dei problemi di seguito per ulteriori 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 dell'account di servizio può essere trovato in Google Cloud Console o nel campo client_email di un file JSON dell'account di servizio scaricato. Gli ID account di servizio sono indirizzi e-mail con il seguente formato: <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:

Node.js

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

Partire

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 account di servizio non sono informazioni sensibili 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, devi anche assicurarti che l'account di servizio utilizzato dall'Admin SDK per effettuare questa chiamata, solitamente {project-name}@appspot.gserviceaccount.com , iam.serviceAccounts.signBlob dell'autorizzazione iam.serviceAccounts.signBlob . Vedere la sezione di risoluzione dei problemi di seguito per ulteriori 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 che si sta autenticando. Questi token scadono dopo un'ora.

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

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)

Partire

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

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

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

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)

Partire

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

Accedi utilizzando token personalizzati sui client

Dopo aver creato un token personalizzato, dovresti inviarlo alla tua app client. L'app client signInWithCustomToken() autenticazione con il token personalizzato chiamando signInWithCustomToken() :

iOS

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

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, il tuo utente verrà ora connesso alla tua app client con l'account specificato uid incluso nel token personalizzato. Se quell'account non esisteva in precedenza, verrà creato un record per quell'utente.

Allo stesso modo degli altri metodi di accesso (come signInWithEmailAndPassword() e signInWithCredential() ), l'oggetto di auth nelle regole del database in tempo reale e l'oggetto request.auth nelle regole di sicurezza di Cloud Storage verranno popolati con l' uid dell'utente. In questo caso, l' uid sarà quello specificato durante la generazione del 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 attestazioni, è possibile auth.token riferimento auth.token (Firebase Realtime Database) o request.auth.token (Cloud Storage) 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 SDK di amministrazione Firebase ufficiale, puoi comunque creare manualmente token personalizzati. Innanzitutto, trova una libreria JWT di terze parti per la tua lingua. Quindi, usa quella libreria JWT per coniare un JWT che include le seguenti affermazioni:

Richieste di token personalizzati
alg Algoritmo "RS256"
iss Emittente L'indirizzo e-mail dell'account di servizio del progetto
sub Soggetto Indirizzo e-mail dell'account di servizio del 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 Il tempo, in secondi dall'epoca UNIX, in cui il token scade. Può essere un massimo di 3600 secondi dopo lo iat .
Nota: questo controlla solo l'ora in cui il token personalizzato scade. Ma una volta che un utente effettua l'accesso utilizzando signInWithCustomToken() , rimarrà signInWithCustomToken() al dispositivo fino a quando la sua sessione non verrà invalidata o l'utente si disconnetterà.
uid L'identificatore univoco dell'utente che ha eseguito l'accesso deve essere una stringa, lunga da 1 a 36 caratteri
claims (facoltativo) Attestazioni personalizzate facoltative da includere nelle variabili auth / request.auth regole di sicurezza

Di seguito sono riportate alcune implementazioni di esempio su 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 informazioni su 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.

Firebase Admin SDK utilizza l' API IAM per firmare i token. Questo errore indica che l'API IAM non è attualmente abilitata per il tuo progetto Firebase. Aprire il collegamento nel messaggio di errore in un browser Web e fare clic sul pulsante "Abilita API" per abilitarlo per il progetto.

L'account di servizio non dispone delle autorizzazioni necessarie

Se l'account di servizio di Firebase Admin SDK è in esecuzione poiché non dispone dell'autorizzazione iam.serviceAccounts.signBlob , potresti ricevere un messaggio di errore come il 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 problema è concedere il ruolo IAM "Creatore token account di servizio" all'account di servizio in questione, solitamente {project-name}@appspot.gserviceaccount.com :

  1. Apri la pagina IAM e amministrazione nella Google Cloud Console.
  2. Seleziona il tuo progetto e fai clic su "Continua".
  3. Fare clic sull'icona di modifica corrispondente all'account di 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.

Fai riferimento alla documentazione IAM per maggiori dettagli su questo processo o scopri come aggiornare i ruoli utilizzando gli strumenti della riga di comando di gcloud.

Impossibile determinare l'account di servizio

Se ricevi un messaggio di errore simile al seguente, significa che 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, assicurarsi di specificare il file JSON dell'account di servizio o l'ID dell'account di servizio durante l'inizializzazione dell'SDK.