Google стремится продвигать расовую справедливость для черных сообществ. Смотри как.
Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Создание пользовательских токенов

Firebase дает вам полный контроль над аутентификацией, позволяя аутентифицировать пользователей или устройства с использованием безопасных веб-токенов JSON (JWT). Вы генерируете эти токены на своем сервере, передаете их обратно на клиентское устройство, а затем используете их для аутентификации с помощью signInWithCustomToken() .

Для этого необходимо создать конечную точку сервера, которая принимает учетные данные для входа, такие как имя пользователя и пароль, и, если учетные данные действительны, возвращает пользовательский JWT. Пользовательский JWT, возвращенный с вашего сервера, может затем использоваться клиентским устройством для аутентификации в Firebase ( iOS , Android , Интернет ). После проверки подлинности эта личность будет использоваться при доступе к другим службам Firebase, таким как база данных Firebase Realtime и облачное хранилище. Кроме того, содержимое JWT будет доступно в объекте auth в ваших Правилах безопасности баз данных Firebase Realtime и в объекте request.auth в ваших Правилах безопасности облачного хранилища .

Вы можете создать собственный токен с помощью Firebase Admin SDK или использовать стороннюю библиотеку JWT, если ваш сервер написан на языке, который Firebase изначально не поддерживает.

Прежде чем начать

Пользовательские токены - это подписанные JWT, где закрытый ключ, используемый для подписи, принадлежит учетной записи службы Google. Существует несколько способов указать учетную запись службы Google, которая должна использоваться в Firebase Admin SDK для подписи пользовательских токенов:

  • Использование файла JSON учетной записи службы - этот метод можно использовать в любой среде, но он требует, чтобы вы упаковали файл JSON учетной записи службы вместе с вашим кодом. Особое внимание необходимо уделить тому, чтобы файл JSON учетной записи службы не был открыт для внешних лиц.
  • Разрешение Admin SDK обнаружить служебную учетную запись - этот метод можно использовать в средах, управляемых Google, таких как Google Cloud Functions и Google App Engine. Возможно, вам придется настроить некоторые дополнительные разрешения через консоль Google Cloud Platform.
  • Использование идентификатора учетной записи службы - при использовании в среде, управляемой Google, этот метод будет подписывать токены с помощью ключа указанной учетной записи службы. Однако он использует удаленную веб-службу, и вам может потребоваться настроить дополнительные разрешения для этой учетной записи службы через консоль Google Cloud Platform.

Использование файла JSON учетной записи службы

Файлы JSON служебной учетной записи содержат всю информацию, соответствующую учетным записям службы (включая закрытый ключ RSA). Их можно скачать с консоли Firebase. Следуйте инструкциям по настройке Admin SDK для получения дополнительной информации о том, как инициализировать Admin SDK с помощью файла JSON учетной записи службы.

Этот метод инициализации подходит для широкого спектра развертываний Admin SDK. Также он позволяет Admin SDK создавать и подписывать пользовательские токены локально, без каких-либо удаленных вызовов API. Основным недостатком этого подхода является то, что он требует упаковки файла JSON учетной записи службы вместе с вашим кодом. Также обратите внимание, что закрытый ключ в файле JSON учетной записи службы является конфиденциальной информацией, поэтому необходимо соблюдать особую осторожность, чтобы сохранить ее конфиденциальность. В частности, воздержитесь от добавления файлов JSON учетной записи службы в общедоступный контроль версий.

Разрешение Admin SDK обнаружить служебную учетную запись

Если ваш код развернут в среде, управляемой Google, Admin SDK может попытаться автоматически обнаружить средство для подписи пользовательских токенов:

  • Если ваш код развернут в стандартной среде Google App Engine для Java, Python или Go, Admin SDK может использовать службу идентификации приложений, присутствующую в этой среде, для подписи пользовательских токенов. Служба идентификации приложений подписывает данные, используя учетную запись службы, предоставленную вашему приложению Google App Engine.

  • Если ваш код развернут в какой-то другой управляемой среде (например, Google Cloud Functions, Google Compute Engine), Firebase Admin SDK может автоматически обнаружить строку идентификатора учетной записи службы с локального сервера метаданных . Обнаруженный идентификатор учетной записи службы затем используется вместе со службой IAM для удаленной подписи токенов.

Чтобы использовать эти методы подписи, инициализируйте SDK с учетными данными Google Application Default и не указывайте строку идентификатора учетной записи службы:

Node.js

 admin.initializeApp();
 

Ява

 FirebaseApp.initializeApp();
 

питон

 default_app = firebase_admin.initialize_app()
 

Идти

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

C #

 FirebaseApp.Create();
 

Для локального тестирования того же кода загрузите файл JSON учетной записи службы и задайте для GOOGLE_APPLICATION_CREDENTIALS переменную среды GOOGLE_APPLICATION_CREDENTIALS .

Если Firebase Admin SDK должен обнаружить строку идентификатора учетной записи службы, он делает это, когда ваш код впервые создает пользовательский токен. Результат кэшируется и используется повторно для последующих операций подписания токена. Автоматически обнаруженный идентификатор учетной записи службы обычно является одной из учетных записей службы по умолчанию, предоставляемой Google Cloud Platform:

Как и в случае с явно указанными идентификаторами учетных записей служб, для автоматического создания идентификаторов учетных записей служб необходимо иметь разрешение iam.serviceAccounts.signBlob . Возможно, вам придется использовать IAM и раздел администрирования консоли Google Cloud Platform, чтобы предоставить учетным записям службы по умолчанию необходимые разрешения. См. Раздел устранения неполадок ниже для получения более подробной информации.

Использование идентификатора учетной записи службы

Чтобы обеспечить согласованность между различными частями вашего приложения, вы можете указать идентификатор учетной записи службы, чьи ключи будут использоваться для подписи токенов при работе в среде, управляемой Google. Это может сделать политики IAM более простыми и безопасными и избежать необходимости включать файл JSON учетной записи службы в ваш код.

Идентификатор учетной записи службы можно найти в консоли Google Cloud Platform или в поле client_email загруженного файла JSON учетной записи службы. Идентификатором учетной записи службы являются адреса электронной почты, имеющие следующий формат: <client-id>@<project-id>.iam.gserviceaccount.com . Они однозначно идентифицируют учетные записи служб в проектах Firebase и Google Cloud Platform.

Чтобы создать пользовательские токены, используя отдельный идентификатор учетной записи службы, инициализируйте SDK, как показано ниже:

Node.js

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

Ява

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

питон

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

Перейти

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

Идентификаторы служебных учетных записей не являются конфиденциальной информацией, и поэтому их воздействие не имеет значения. Однако для подписи пользовательских токенов с помощью указанной учетной записи службы Firebase Admin SDK должен вызвать удаленную службу. Кроме того, вы также должны убедиться, что служебная учетная запись, которую использует Admin SDK для выполнения этого вызова - обычно {project-name}@appspot.gserviceaccount.com name {project-name}@appspot.gserviceaccount.com - имеет разрешение iam.serviceAccounts.signBlob . См. Раздел устранения неполадок ниже для более подробной информации.

Создавайте собственные токены с помощью Firebase Admin SDK

Firebase Admin SDK имеет встроенный метод для создания пользовательских токенов. Как минимум, вы должны предоставить uid пользователя , который может быть любой строкой , но должен однозначно идентифицировать пользователя или устройства , их подлинности. Срок действия этих токенов истекает через час.

Node.js

 let uid = 'some-uid';

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

Ява

 String uid = "some-uid";

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

питон

 uid = 'some-uid'

custom_token = auth.create_custom_token(uid) 

Перейти

 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
 

Вы также можете при желании указать дополнительные претензии, которые будут включены в пользовательский токен. Например, ниже, к premiumAccount поле premiumAccount , которое будет доступно в объектах auth / request.auth в ваших Правилах безопасности:

Node.js

 let userId = 'some-uid';
let additionalClaims = {
  premiumAccount: true
};

admin.auth().createCustomToken(userId, additionalClaims)
  .then(function(customToken) {
    // Send token back to client
  })
  .catch(function(error) {
    console.log('Error creating custom token:', error);
  });
 

Ява

 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
 

питон

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

custom_token = auth.create_custom_token(uid, additional_claims) 

Перейти

 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
 

Войдите с помощью пользовательских токенов на клиентах

После создания пользовательского токена вы должны отправить его в ваше клиентское приложение. Клиентское приложение аутентифицируется с помощью пользовательского токена, вызывая signInWithCustomToken() :

IOS

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

единство

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

Web

 firebase.auth().signInWithCustomToken(token).catch(function(error) {
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // ...
});
 

Если аутентификация прошла успешно, ваш пользователь теперь войдет в ваше клиентское приложение с учетной записью, указанной в uid включенном в пользовательский токен. Если эта учетная запись ранее не существовала, будет создана запись для этого пользователя.

Так же, как и с другими методами входа (такими как signInWithEmailAndPassword() и signInWithCredential() ), объект auth в ваших Правилах безопасности баз данных Firebase Realtime и объект request.auth в ваших Правилах безопасности облачного хранилища будут заполняться пользователем uid . В этом случае uid будет тем, который вы указали при создании пользовательского токена.

Правила базы данных

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

Правила хранения

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

Если пользовательский токен содержит дополнительные утверждения, на них можно ссылаться из auth.token (база данных Firebase Realtime) или request.auth.token (облачное хранилище) в ваших правилах:

Правила базы данных

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

Правила хранения

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

Создание пользовательских токенов с использованием сторонней библиотеки JWT

Если ваш бэкэнд написан на языке, на котором нет официального SDK Firebase Admin, вы все равно можете вручную создавать собственные токены. Сначала найдите стороннюю библиотеку JWT для вашего языка. Затем используйте эту библиотеку JWT для создания JWT, который включает в себя следующие утверждения:

Пользовательские токены
alg алгоритм "RS256"
iss эмитент Адрес электронной почты учетной записи службы вашего проекта
sub предмет Адрес электронной почты учетной записи службы вашего проекта
aud аудитория "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Выдается вовремя Текущее время в секундах с эпохи UNIX
exp Время истечения Время в секундах с начала эпохи UNIX, в которое истекает токен. Это может быть максимум 3600 секунд позже, чем iat .
Примечание: это контролирует только время истечения самого токена . Но как только вы signInWithCustomToken() в систему с помощью signInWithCustomToken() , он останется signInWithCustomToken() в устройство, пока его сеанс не будет признан недействительным или пользователь не выйдет из системы.
uid Уникальный идентификатор вошедшего в систему пользователя должен быть строкой длиной от 1 до 36 символов
claims (необязательно) Необязательные пользовательские утверждения для включения в правила безопасности переменных auth / request.auth

Вот несколько примеров реализации того, как создавать собственные токены на разных языках, которые не поддерживает Firebase Admin SDK:

PHP

Использование 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");
}
 

рубин

Использование 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
 

После того как вы создадите пользовательский токен, отправьте его в ваше клиентское приложение, чтобы использовать для аутентификации в Firebase. Смотрите примеры кода выше, чтобы узнать, как это сделать.

поиск неисправностей

В этом разделе описываются некоторые распространенные проблемы, с которыми могут столкнуться разработчики при создании пользовательских токенов, и способы их решения.

API IAM не включен

Если вы указываете идентификатор учетной записи службы для подписи токенов, вы можете получить сообщение об ошибке, подобное следующему:

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 использует IAM API для подписи токенов. Эта ошибка указывает на то, что IAM API в настоящее время не включен для вашего проекта Firebase. Откройте ссылку в сообщении об ошибке в веб-браузере и нажмите кнопку «Включить API», чтобы включить ее для своего проекта.

Учетная запись службы не имеет необходимых разрешений

Если служебная учетная запись, которую запускает Firebase Admin SDK, не имеет разрешения iam.serviceAccounts.signBlob , вы можете получить сообщение об ошибке, подобное следующему:

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

Самый простой способ решить эту проблему - предоставить роль IAM «Создатель токена учетной записи службы» соответствующей учетной записи службы, обычно {project-name}@appspot.gserviceaccount.com :

  1. Откройте страницу IAM и администрирования в консоли Google Cloud Platform.
  2. Выберите ваш проект и нажмите «Продолжить».
  3. Нажмите значок редактирования, соответствующий учетной записи службы, которую вы хотите обновить.
  4. Нажмите «Добавить еще одну роль».
  5. Введите «Создатель токена учетной записи службы» в поисковый фильтр и выберите его из результатов.
  6. Нажмите «Сохранить», чтобы подтвердить предоставление роли.

Обратитесь к документации IAM для получения более подробной информации об этом процессе или узнайте, как выполнять обновление ролей с помощью инструментов командной строки gcloud.

Не удалось определить учетную запись службы

Если вы получаете сообщение об ошибке, подобное следующему, Firebase Admin SDK не был правильно инициализирован.

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

Если вы используете пакет SDK для автоматического обнаружения идентификатора учетной записи службы, убедитесь, что код развернут в управляемой среде Google с сервером метаданных. В противном случае обязательно укажите файл JSON учетной записи службы или идентификатор учетной записи службы при инициализации SDK.