Özel Jetonlar Oluşturma

Firebase, aşağıdakileri yaparak kimlik doğrulama üzerinde tam kontrol sağlar: Güvenli JSON Web Jetonları (JWT'ler) kullanarak kullanıcıların veya cihazların kimliğini doğrulama. Sizin oluşturduğunuz sunucu üzerinde kontrol edip bir istemci cihazına geri iletmeli ve daha sonra bu kullanıcıların kimliklerini signInWithCustomToken() yöntemiyle doğrulamalarını öneririz.

Bunu başarmak için, oturum açmayı kabul eden bir sunucu uç noktası oluşturmanız gerekir kimlik bilgileri (ör. kullanıcı adı ve şifre) ve kimlik bilgileri geçerli, özel bir JWT döndürür. Sunucunuzdan döndürülen özel JWT, Firebase ile kimlik doğrulamak için bir istemci cihazı tarafından kullanılmalıdır (iOS+, Android, web) kullanıyor. Kimlik doğrulandıktan sonra bu kimlik Firebase Realtime Database gibi diğer Firebase hizmetlerine erişilirken kullanılır ve Cloud Storage. Ayrıca, JWT'nin içeriği, auth nesnesinde kullanılabilir Realtime Database Security Rules ve request.auth nesne Cloud Storage Security Rules.

Firebase Admin SDK ile özel jeton oluşturabilir veya Sunucunuz şu dilde yazılmışsa üçüncü taraf bir JWT kitaplığını kullanabilirsiniz: Firebase'in yerel olarak desteklemediği bir dil.

Başlamadan önce

Özel jetonlar, imzalama için kullanılan özel anahtarın ait olduğu imzalı JWT'lerdir. bir Google hizmet hesabı oluşturun. Google hizmetini belirtmenin birkaç yolu vardır Firebase Admin SDK'sı tarafından özel imzalama işlemi için kullanılması gereken bir hesap jetonlar:

  • Bir hizmet hesabı JSON dosyası kullanarak -- Bu yöntem ancak bir hizmet hesabı JSON dosyasını paketlemenizi gerektirir kodunuza ekler. hizmet hesabı JSON dosyası harici taraflara sunulmaz.
  • Yönetici SDK'sının bir hizmet hesabını bulmasına izin verme -- Bu yöntem Google Cloud gibi Google tarafından yönetilen ortamlarda kullanılabilir İşlevler ve App Engine. Bazı görevleri ve Google Cloud konsolu üzerinden ek izinler sağlayabilirsiniz.
  • Hizmet hesabı kimliği kullanarak -- Bu yöntem, Google tarafından yönetilen bir ortamda kullanıldığında jetonları belirtilen hizmet hesabının anahtarını kullanın. Ancak uzaktan web hizmetini kullanır ve bu nedenle bu hizmet hesabı için ek izinler: Google Cloud konsolu.

Hizmet hesabı JSON dosyası kullanma

Hizmet hesabı JSON dosyaları, hizmete karşılık gelen tüm bilgileri içerir (RSA özel anahtarı dahil). Buradan indirilebilirler: Firebase konsolu. Yönetici SDK'sı kurulumunu uygulayın. daha fazla bilgi için Yönetici SDK'sını bir hizmet hesabı JSON dosyasıyla başlatın.

Bu başlatma yöntemi, birçok yönetici SDK'sı için uygundur dağıtımları. Ayrıca Admin SDK'nın özel jetonlar oluşturmasını ve imzalamasını sağlar herhangi bir uzak API çağrısı yapmadan yerel olarak. Bunun temel dezavantajı, bir hizmet hesabı JSON dosyası paketlemenizi gerektirmesidir. kodunuza ekler. Ayrıca, bir hizmet hesabındaki özel anahtarın JSON dosyası hassas bilgiler içerdiğinden, bunların kabul etmesini sağlar. Özellikle, hizmet hesabı JSON dosyaları eklemekten kaçının herkese açık sürüm denetimine.

Yönetici SDK'sinin bir hizmet hesabını bulmasına izin verme

Kodunuz Google tarafından yönetilen bir ortamda dağıtıldıysa Admin SDK özel jetonları imzalama yollarını otomatik olarak bulmaya çalışabilir:

  • Kodunuz App Engine için standart ortamda dağıtılırsa Admin SDK, JavaScript'i veya Uygulama Kimliği hizmeti bulunması gerekir. Uygulama Kimliği hizmeti Verileri, uygulamanız için Google Uygulaması tarafından sağlanan bir hizmet hesabını kullanarak imzalar Motor.

  • Kodunuz Google Cloud gibi başka bir yönetilen ortamda dağıtıldıysa İşlevleri, Google Compute Engine), Firebase Admin SDK'sı kullanıcı aracısına otomatik olarak bir yerel dildeki hizmet hesabı kimliği dizesi meta veri sunucusuyla uyumludur. Keşfedilen hizmet hesabı kimliği daha sonra IAM ile birlikte kullanılır. hizmeti sunar.

Bu imzalama yöntemlerinden yararlanmak için SDK'yı Google ile başlatın Uygulama Varsayılan kimlik bilgileri ve hizmet hesabı kimliği dizesi belirtmeyin:

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

Aynı kodu yerel olarak test etmek için bir hizmet hesabı JSON dosyası indirin ve GOOGLE_APPLICATION_CREDENTIALS ortam değişkeni ekleyin.

Firebase Admin SDK'nın bir hizmet hesabı kimliği dizesi keşfetmesi gerektiğinde Bu nedenle kodunuz ilk kez özel jeton oluşturduğunda. Sonuç önbelleğe alınır ve sonraki jeton imzalama işlemleri için yeniden kullanılır. Otomatik olarak keşfedilen hizmet hesabı kimliği genellikle varsayılan hizmetlerden biridir. Google Cloud tarafından sağlanan hesaplar:

Açıkça belirtilen hizmet hesabı kimliklerinde olduğu gibi otomatik olarak keşfedilen hizmet de hesap kimliklerininiam.serviceAccounts.signBlob düzgün şekilde çalışmasını sağlamalısınız. Bunun için IAM ve yönetici bölümü Google Cloud konsolunun varsayılan hizmet hesaplarına gerekli izinleri verebilirsiniz. Daha ayrıntılı bilgi için aşağıdaki sorun giderme bölümüne bakın.

Hizmet hesabı kimliği kullanma

Uygulamanızın çeşitli bölümleri arasında tutarlılığı korumak için şunları yapabilirsiniz: çalışırken jetonları imzalamak için anahtarları kullanılacak bir hizmet hesabı kimliği belirtin Google tarafından yönetilen bir ortamda saklanır. Bu, IAM politikalarını daha basit ve güvenli hale getirebilir ve hizmet hesabı JSON dosyasını kodunuza ekleyin.

Hizmet hesabı kimliği şurada bulunabilir: Google Cloud konsolu, veya indirilen bir hizmet hesabı JSON dosyasının client_email alanında kullanılabilir. Hizmet hesabı kimlikleri, aşağıdaki biçimde olan e-posta adresleridir: <client-id>@<project-id>.iam.gserviceaccount.com Benzersiz bir şekilde Firebase'deki ve Google Cloud projelerindeki hizmet hesaplarında kullanılabilir.

Ayrı bir hizmet hesabı kimliği kullanarak özel jetonlar oluşturmak için SDK'yı başlatın aşağıdaki gibidir:

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

Hizmet hesabı kimlikleri hassas bilgiler değildir ve bu nedenle açığa çıkarılmaları alakasızdır. Bununla birlikte, belirtilen hizmetle özel jetonlar imzalamak için Firebase Admin SDK'nın uzak bir hizmeti çağırması gerekir. Ayrıca, Yönetici SDK'si hizmet hesabının bu aramayı yapmak için kullanılıyor —genellikle {project-name}@appspot.gserviceaccount.comiam.serviceAccounts.signBlob özelliğine sahip izni. Daha ayrıntılı bilgi için aşağıdaki sorun giderme bölümüne bakın.

Firebase Admin SDK'yı kullanarak özel jetonlar oluşturma

Firebase Admin SDK'da, özel jetonlar oluşturmak için yerleşik bir yöntem bulunur. Kuyruklu a işareti en azından bir uid sağlamanız gerekir. Bu, herhangi bir dize olabilir ancak kimliğini doğruladığınız kullanıcıyı veya cihazı benzersiz şekilde tanımlar. Bu jetonların geçerlilik süresi sona erer bir saat sonra takip edebilirsiniz.

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

İsterseniz özel rapora eklenecek ek hak talepleri de belirtebilirsiniz. jeton. Örneğin, aşağıdaki URL'ye bir premiumAccount alanı eklenmiştir: auth / request.auth nesnelerinde bulunacak özel jeton güvenlik kurallarınızda:

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

Ayrılmış özel jeton adları

İstemcilerde özel jeton kullanarak oturum açın

Özel jeton oluşturduktan sonra bu jetonu istemci uygulamanıza göndermeniz gerekir. İlgili içeriği oluşturmak için kullanılan istemci uygulaması, şunu çağırarak özel jetonla kimlik doğrular: signInWithCustomToken():

iOS ve üzeri

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

Unity

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

Kimlik doğrulama başarılı olursa, kullanıcınız şimdi oturum açtığınızda özel dosyaya dahil edilen uid ile belirtilen hesapla istemci uygulaması jeton. Bu hesap daha önce oluşturulmamışsa bu kullanıcının kaydı oluşturuldu.

Bu yöntem, diğer oturum açma yöntemlerinde (ör. signInWithEmailAndPassword() ve signInWithCredential()) auth nesnesini tanımlayın Realtime Database Security Rules ve request.auth nesnesindeki Cloud Storage Security Rules kullanıcının uid ile doldurulur. Bu durumda, uid öğesi özel jetonu oluştururken belirttiğinizdir.

Veritabanı Kuralları

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

Depolama Kuralları

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

Özel jeton ek hak talepleri içeriyorsa bunlara şuradan referans verilebilir: auth.token (Firebase Realtime Database) veya request.auth.token Kurallarınızda (Cloud Storage) nesne:

Veritabanı Kuralları

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

Depolama Kuralları

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

Üçüncü taraf JWT kitaplığı kullanarak özel jetonlar oluşturma

Arka ucunuz resmi bir Firebase Yöneticisi olmayan bir dildeyse SDK'yı kullanıyorsanız özel jetonları manuel olarak oluşturmaya devam edebilirsiniz. İlk olarak, Kendi dilinize uygun bir üçüncü taraf JWT kitaplığı bulun. Daha sonra JWT kitaplığının aşağıdaki iddiaları içeren bir JWT'yi işlemesi için kullanılır:

Özel Jeton Hak Talepleri
alg Algoritma "RS256"
iss Düzenleyen Projenizin hizmet hesabı e-posta adresi
sub Konu Projenizin hizmet hesabı e-posta adresi
aud Kitle "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Yayınlanma zamanı UNIX döneminden bu yana geçen saniye cinsinden geçerli zaman
exp Geçerlilik süresi Jetonun süresinin dolacağı UNIX döneminden beri geçen süre (saniye cinsinden). Google iat değerinden en fazla 3.600 saniye sonra olabilir.
. Not: Bu yalnızca özel jetonun sona erecektir. Ancak bir kullanıcının, yeni bir uygulama ya da signInWithCustomToken(), oturumu geçersiz kılınana veya kullanıcı oturumu kapatana kadar cihazı kullanmaya devam edebilir.
uid Oturum açmış kullanıcının benzersiz tanımlayıcısı, 1-128 karakter uzunluğunda (bu değerler dahil). Daha kısa uid değerleri daha iyi sonuç verir bazı yolları da görmüştük.
claims (isteğe bağlı) Güvenlik Kurallarına dahil edilecek isteğe bağlı özel hak talepleri auth / request.auth değişken

Burada, Firebase Admin SDK'nın desteklemediği çeşitli diller:

PHP

php-jwt kullanıldığında:

// 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

ruby-jwt kullanıldığında:

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

Özel jetonu oluşturduktan sonra Firebase ile kimlik doğrulama. Bunu nasıl yapacağınızı öğrenmek için yukarıdaki kod örneklerini inceleyin.

Sorun giderme

Bu bölümde, geliştiricilerin ödeme yaparken karşılaşabilecekleri bazı yaygın sorunlar ve bunların nasıl çözüleceğini öğreneceksiniz.

IAM API etkin değil

Jetonları imzalamak için bir hizmet hesabı kimliği belirtiyorsanız şuna benzer bir hata:

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'sı IAM API kullanabilirsiniz. Bu hata, IAM API'nin şu anda etkin olmadığını gösterir CANNOT TRANSLATE Firebase projesi. Hata mesajındaki bağlantıyı bir web tarayıcısında açın ve "API'yi etkinleştir"i tıklayın. düğmesini tıklayarak projeniz için etkinleştirin.

Hizmet hesabı gerekli izinlere sahip değil

Firebase Admin SDK'nın çalıştığı hizmet hesabı iam.serviceAccounts.signBlob izniniz varsa şuna benzer bir hata mesajı alabilirsiniz: şu:

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

Bunu çözmenin en kolay yolu "Hizmet Hesabı Jetonu Oluşturucu"yu vermektir Söz konusu hizmet hesabına IAM rolü ekleyin, genellikle {project-name}@appspot.gserviceaccount.com:

  1. IAM ve yönetici sayfasını açın. Google Cloud konsolunda görebilirsiniz.
  2. Projenizi seçin ve "Continue" (Devam) düğmesini tıklayın.
  3. Güncellemek istediğiniz hizmet hesabına karşılık gelen düzenle simgesini tıklayın.
  4. "Başka bir rol ekle"yi tıklayın.
  5. "Hizmet Hesabı Jetonu Oluşturucu" yazın arama filtresine girip bunu daha fazla bilgi edindiniz.
  6. "Kaydet"i tıklayın. tıklayın.

IAM belgelerini inceleyin daha fazla bilgi almak veya gcloud komut satırı araçları.

Hizmet hesabı belirlenemedi

Aşağıdakine benzer bir hata mesajı alırsanız Firebase Admin SDK'sı gerektiği gibi başlatılmadı.

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

Bir hizmet hesabı kimliğini otomatik olarak keşfetmesi için SDK'dan yararlanıyorsanız Kod, bir meta veri sunucusuyla yönetilen Google ortamına dağıtılır. Aksi takdirde, hizmet hesabı JSON dosyasını veya hizmet hesabı kimliğini belirttiğinizden emin olun hale getirir.