Özel Jetonlar Oluşturun

Firebase, güvenli JSON Web Belirteçlerini (JWT'ler) kullanarak kullanıcıların veya cihazların kimliğini doğrulamanıza olanak tanıyarak kimlik doğrulama üzerinde tam kontrol sahibi olmanızı sağlar. Bu belirteçleri sunucunuzda oluşturursunuz, bunları bir istemci cihaza geri aktarırsınız ve ardından bunları, signInWithCustomToken() yöntemi aracılığıyla kimlik doğrulaması yapmak için kullanırsınız.

Bunu başarmak için, kullanıcı adı ve parola gibi oturum açma kimlik bilgilerini kabul eden ve kimlik bilgileri geçerliyse özel bir JWT döndüren bir sunucu uç noktası oluşturmanız gerekir. Sunucunuzdan döndürülen özel JWT daha sonra bir istemci cihazı tarafından Firebase ( iOS+ , Android , web ) ile kimlik doğrulaması yapmak için kullanılabilir. Kimlik doğrulaması yapıldıktan sonra bu kimlik, Firebase Gerçek Zamanlı Veritabanı ve Bulut Depolama gibi diğer Firebase hizmetlerine erişilirken kullanılacaktır. Ayrıca JWT'nin içeriği, Gerçek Zamanlı Veritabanı Güvenliği Kurallarınızdaki auth nesnesinde ve Bulut Depolama Güvenlik Kurallarınızdaki request.auth nesnesinde mevcut olacaktır.

Firebase Admin SDK ile özel bir belirteç oluşturabilir veya sunucunuz Firebase'in yerel olarak desteklemediği bir dilde yazılmışsa üçüncü taraf bir JWT kitaplığı kullanabilirsiniz.

Sen başlamadan önce

Özel belirteçler, imzalama için kullanılan özel anahtarın bir Google hizmet hesabına ait olduğu imzalı JWT'lerdir. Özel belirteçleri imzalamak için Firebase Yönetici SDK'sı tarafından kullanılması gereken Google hizmet hesabını belirtmenin birkaç yolu vardır:

  • Hizmet hesabı JSON dosyasını kullanma -- Bu yöntem herhangi bir ortamda kullanılabilir ancak kodunuzla birlikte bir hizmet hesabı JSON dosyasını da paketlemenizi gerektirir. Hizmet hesabı JSON dosyasının harici tarafların eline geçmemesini sağlamak için özel dikkat gösterilmelidir.
  • Yönetici SDK'sının bir hizmet hesabı bulmasına izin verme -- Bu yöntem, Google Cloud Functions ve App Engine gibi Google tarafından yönetilen ortamlarda kullanılabilir. Google Cloud konsolu aracılığıyla bazı ek izinleri yapılandırmanız gerekebilir.
  • Hizmet hesabı kimliğini kullanma -- Google tarafından yönetilen bir ortamda kullanıldığında bu yöntem, belirteçleri belirtilen hizmet hesabının anahtarını kullanarak imzalar. Ancak uzak bir web hizmeti kullanır ve Google Cloud konsolu aracılığıyla bu hizmet hesabı için ek izinler yapılandırmanız gerekebilir.

Hizmet hesabı JSON dosyasını kullanma

Hizmet hesabı JSON dosyaları, hizmet hesaplarına karşılık gelen tüm bilgileri içerir (RSA özel anahtarı dahil). Firebase konsolundan indirilebilirler. Yönetici SDK'sının bir hizmet hesabı JSON dosyasıyla nasıl başlatılacağı hakkında daha fazla bilgi için Yönetici SDK'sı kurulum talimatlarını izleyin.

Bu başlatma yöntemi, çok çeşitli Yönetici SDK dağıtımları için uygundur. Ayrıca Yönetici SDK'sının herhangi bir uzaktan API çağrısı yapmadan özel belirteçleri yerel olarak oluşturmasına ve imzalamasına olanak tanır. Bu yaklaşımın ana dezavantajı, kodunuzla birlikte bir hizmet hesabı JSON dosyasını paketlemenizi gerektirmesidir. Ayrıca, bir hizmet hesabı JSON dosyasındaki özel anahtarın hassas bilgiler olduğunu ve gizli tutulmasına özel dikkat gösterilmesi gerektiğini unutmayın. Özellikle, hizmet hesabı JSON dosyalarını genel sürüm kontrolüne eklemekten kaçının.

Admin SDK'nın bir hizmet hesabı bulmasına izin verme

Kodunuz Google tarafından yönetilen bir ortamda dağıtıldıysa Yönetici SDK'sı, özel jetonları imzalamaya yönelik bir yöntemi otomatik olarak keşfetmeyi deneyebilir:

  • Kodunuz Java, Python veya Go için App Engine standart ortamında dağıtıldıysa Yönetici SDK'sı, özel belirteçleri imzalamak için o ortamda bulunan Uygulama Kimliği hizmetini kullanabilir. Uygulama Kimliği hizmeti, uygulamanız için Google App Engine tarafından sağlanan bir hizmet hesabını kullanarak verileri imzalar.

  • Kodunuz başka bir yönetilen ortamda (ör. Google Cloud Functions, Google Compute Engine) dağıtıldıysa Firebase Admin SDK, yerel meta veri sunucusundan bir hizmet hesabı kimliği dizesini otomatik olarak bulabilir. Keşfedilen hizmet hesabı kimliği daha sonra belirteçleri uzaktan imzalamak için IAM hizmetiyle birlikte kullanılır.

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

Node.js

initializeApp();

Java

FirebaseApp.initializeApp();

Python

default_app = firebase_admin.initialize_app()

Gitmek

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şkenini onu işaret edecek şekilde ayarlayın.

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

Açıkça belirtilen hizmet hesabı kimliklerinde olduğu gibi, otomatik keşfedilen hizmet hesabı kimliklerinin, özel belirteç oluşturma işleminin çalışması için iam.serviceAccounts.signBlob iznine sahip olması gerekir. Varsayılan hizmet hesaplarına gerekli izinleri vermek için Google Cloud konsolunun IAM ve yönetici bölümünü kullanmanız gerekebilir. Daha fazla ayrıntı için aşağıdaki sorun giderme bölümüne bakın.

Hizmet hesabı kimliğini kullanma

Uygulamanızın çeşitli bölümleri arasında tutarlılığı korumak için, Google tarafından yönetilen bir ortamda çalıştırılırken anahtarları jetonları imzalamak için kullanılacak bir hizmet hesabı kimliği belirtebilirsiniz. Bu, IAM politikalarını daha basit ve daha güvenli hale getirebilir ve hizmet hesabı JSON dosyasını kodunuza dahil etme zorunluluğunu ortadan kaldırabilir.

Hizmet hesabı kimliği, Google Cloud konsolunda veya indirilen hizmet hesabı JSON dosyasının client_email alanında bulunabilir. Hizmet hesabı kimlikleri şu biçime sahip e-posta adresleridir: <client-id>@<project-id>.iam.gserviceaccount.com . Firebase ve Google Cloud projelerindeki hizmet hesaplarını benzersiz şekilde tanımlarlar.

Ayrı bir hizmet hesabı kimliği kullanarak özel belirteçler oluşturmak için SDK'yı aşağıda gösterildiği gibi başlatın:

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)

Gitmek

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 bunların açığa çıkması önemsizdir. Ancak özel belirteçleri belirtilen hizmet hesabıyla imzalamak için Firebase Yönetici SDK'sının uzak bir hizmeti çağırması gerekir. Ayrıca, Yönetici SDK'sının bu çağrıyı yapmak için kullandığı hizmet hesabının (genellikle {project-name}@appspot.gserviceaccount.com ) iam.serviceAccounts.signBlob iznine sahip olduğundan da emin olmalısınız. Daha fazla ayrıntı için aşağıdaki sorun giderme bölümüne bakın.

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

Firebase Yönetici SDK'sında özel belirteçler oluşturmaya yönelik yerleşik bir yöntem bulunur. En azından, herhangi bir dize olabilen ancak kimliğini doğruladığınız kullanıcıyı veya cihazı benzersiz şekilde tanımlaması gereken bir uid sağlamanız gerekir. Bu jetonların geçerliliği bir saat sonra sona erer.

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)

Gitmek

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

Ayrıca isteğe bağlı olarak özel belirtece dahil edilecek ek talepleri de belirtebilirsiniz. Örneğin, aşağıda, Güvenlik Kurallarınızdaki auth / request.auth nesnelerinde mevcut olacak özel belirtece bir premiumAccount alanı eklenmiştir:

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)

Gitmek

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 belirteçler kullanarak oturum açın

Özel bir belirteç oluşturduktan sonra bunu istemci uygulamanıza göndermelisiniz. İstemci uygulaması, signInWithCustomToken() öğesini çağırarak özel belirteçle kimlik doğrulaması yapar:

iOS+

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

Birlik

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 ad alanlı API

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

Web modüler API'si

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 artık özel belirteçte yer alan uid tarafından belirtilen hesapla istemci uygulamanızda oturum açacaktır. Eğer bu hesap daha önce mevcut değilse o kullanıcı için bir kayıt oluşturulacaktır.

Diğer oturum açma yöntemlerinde olduğu gibi ( signInWithEmailAndPassword() signInWithCredential() gibi) Gerçek Zamanlı Veritabanı Güvenlik Kurallarınızdaki auth nesnesi ve Bulut Depolama Güvenlik Kurallarınızdaki request.auth nesnesi kullanıcının kullanıcı uid doldurulacaktır. . Bu durumda uid , özel belirteci oluştururken belirttiğiniz kullanıcı kimliği olacaktır.

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 belirteç ek talepler içeriyorsa kurallarınızdaki auth.token (Firebase Gerçek Zamanlı Veritabanı) veya request.auth.token (Bulut Depolama) nesnesinden bunlara başvurulabilir:

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ığını kullanarak özel belirteçler oluşturun

Arka ucunuz resmi Firebase Admin SDK'sı olmayan bir dildeyse yine de manuel olarak özel jetonlar oluşturabilirsiniz. Öncelikle dilinize uygun bir üçüncü taraf JWT kütüphanesi bulun . Ardından, aşağıdaki talepleri içeren bir JWT oluşturmak için bu JWT kitaplığını kullanın:

Özel Jeton Talepleri
alg Algoritma "RS256"
iss İhraççı Projenizin hizmet hesabı e-posta adresi
sub Ders Projenizin hizmet hesabı e-posta adresi
aud Kitle "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Yayınlandığı tarihte UNIX çağından bu yana saniye cinsinden şimdiki zaman
exp son kullanma süresi UNIX döneminden bu yana belirtecin süresinin dolduğu saniye cinsinden süre. iat maksimum 3600 saniye sonra olabilir.
Not: Bu yalnızca özel belirtecin süresinin dolduğu zamanı kontrol eder. Ancak bir kullanıcının oturumunu bir kez signInWithCustomToken() kullanarak açtığınızda, oturumları geçersiz kılınıncaya veya kullanıcı oturumu kapatana kadar cihazda oturum açmış olarak kalacaktır.
uid Oturum açan kullanıcının benzersiz tanımlayıcısı, 1-128 karakter uzunluğunda (dahil) bir dize olmalıdır. Daha kısa uid daha iyi performans sunar.
claims (isteğe bağlı) Güvenlik Kuralları auth / request.auth değişkenlerine dahil edilecek isteğe bağlı özel talepler

Firebase Admin SDK'nın desteklemediği çeşitli dillerde özel belirteçlerin nasıl oluşturulacağına ilişkin bazı örnek uygulamalar şunlardır:

PHP

php-jwt kullanarak:

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

Yakut

ruby-jwt kullanma:

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ğrulamasında kullanmak üzere istemci uygulamanıza gönderin. Bunun nasıl yapılacağını öğrenmek için yukarıdaki kod örneklerine bakın.

Sorun giderme

Bu bölümde, geliştiricilerin özel belirteçler oluştururken karşılaşabileceği bazı genel sorunlar ve bunların nasıl çözüleceği özetlenmektedir.

IAM API etkin değil

Belirteçleri imzalamak için bir hizmet hesabı kimliği belirtiyorsanız aşağıdakine benzer bir hatayla karşılaşabilirsiniz:

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

Hizmet hesabı gerekli izinlere sahip değil

Firebase Admin SDK'nın çalıştığı hizmet hesabı iam.serviceAccounts.signBlob iznine sahip değilse aşağıdakine benzer bir hata mesajı alabilirsiniz:

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

Bu sorunu çözmenin en kolay yolu, söz konusu hizmet hesabına (genellikle {project-name}@appspot.gserviceaccount.com "Hizmet Hesabı Belirteci Oluşturucu" IAM rolünü vermektir:

  1. Google Cloud konsolunda IAM ve yönetici sayfasını açın.
  2. Projenizi seçin ve "Devam Et"e tıklayın.
  3. Güncellemek istediğiniz hizmet hesabına karşılık gelen düzenleme simgesini tıklayın.
  4. "Başka Bir Rol Ekle"ye tıklayın.
  5. Arama filtresine "Hizmet Hesabı Token Oluşturucu" yazın ve sonuçlardan seçin.
  6. Rol atamasını onaylamak için "Kaydet"i tıklayın.

Bu süreç hakkında daha fazla ayrıntı için IAM belgelerine bakın veya gcloud komut satırı araçlarını kullanarak rolleri nasıl güncelleyeceğinizi öğrenin.

Hizmet hesabı belirlenemedi

Aşağıdakine benzer bir hata mesajı alırsanız Firebase Admin SDK düzgün şekilde başlatılmamış demektir.

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 bulmak için SDK'ya güveniyorsanız kodun, meta veri sunucusuyla yönetilen bir Google ortamında dağıtıldığından emin olun. Aksi takdirde, SDK başlatma sırasında hizmet hesabı JSON dosyasını veya hizmet hesabı kimliğini belirttiğinizden emin olun.