Firebase zapewnia pełną kontrolę nad uwierzytelnianiem, umożliwiając:
uwierzytelniać użytkowników lub urządzenia przy użyciu bezpiecznych tokenów sieciowych JSON (JWT). Generujesz
te tokeny na serwerze, przekaż je z powrotem do urządzenia klienckiego, a następnie użyj
ich uwierzytelnienie za pomocą metody signInWithCustomToken()
.
Aby to osiągnąć, musisz utworzyć punkt końcowy serwera, który akceptuje logowanie
danych logowania (takich jak nazwa użytkownika i hasło), a jeśli dane logowania
Prawidłowy, zwraca niestandardowy token JWT. Niestandardowy token JWT zwrócony z serwera może wtedy
być używane przez urządzenie klienckie do uwierzytelniania w Firebase
(iOS+, Android,
sieć). Po uwierzytelnieniu ta tożsamość zostanie
używane przy uzyskiwaniu dostępu do innych usług Firebase, takich jak Firebase Realtime Database
i Cloud Storage. Ponadto zawartość tokena JWT będzie
dostępna w obiekcie auth
w
Realtime Database Security Rules oraz
request.auth
obiekt w
Cloud Storage Security Rules
Możesz utworzyć token niestandardowy za pomocą pakietu Firebase Admin SDK lub użyj zewnętrznej biblioteki JWT, jeśli Twój serwer jest zapisany w Język, którego Firebase nie obsługuje natywnie.
Zanim zaczniesz
Tokeny niestandardowe to podpisane tokeny JWT, do których należy klucz prywatny używany do podpisywania konto usługi Google. Usługę Google można określić na kilka sposobów konto, które powinno być używane przez pakiet Firebase Admin SDK do podpisywania niestandardowego tokeny:
- Użycie pliku JSON konta usługi – Metoda ta może być używana w każdym środowisko, ale wymaga pakietu pliku JSON konta usługi wraz z kodem. Zachowaj szczególną ostrożność, aby sprawdzić, czy Plik JSON konta usługi nie jest dostępny dla osób zewnętrznych.
- Zezwalanie pakietowi Admin SDK na wykrywanie konta usługi -- Ta metoda można używać w środowiskach zarządzanych przez Google, takich jak Google Cloud Funkcje i App Engine. Konieczne może być skonfigurowanie dodatkowych uprawnień w konsoli Google Cloud.
- Używanie identyfikatora konta usługi – W środowisku zarządzanym przez Google ta metoda będzie podpisywać tokeny za pomocą: klucza określonego konta usługi. Korzysta jednak ze zdalnej usługi sieciowej i może być konieczne skonfigurowanie dodatkowych uprawnień dla tego konta usługi za pośrednictwem Konsola Google Cloud.
Za pomocą pliku JSON konta usługi
Pliki JSON konta usługi zawierają wszystkie informacje powiązane z usługą (w tym klucz prywatny RSA). Można je pobrać z Konsola Firebase. Postępuj zgodnie z instrukcjami konfiguracji pakietu Admin SDK , gdzie znajdziesz więcej informacji o tym, zainicjować pakiet Admin SDK plikiem JSON konta usługi.
Ta metoda inicjowania jest odpowiednia w przypadku wielu różnych pakietów Admin SDK wdrożeniach. Umożliwia też tworzenie i podpisywanie tokenów niestandardowych za pomocą pakietu Admin SDK. lokalnie, bez wykonywania zdalnych wywołań interfejsu API. Główną wadą polega na tym, że musisz spakować plik JSON konta usługi wraz z kodem. Pamiętaj też, że klucz prywatny konta usługi Plik JSON zawiera informacje poufne i należy zachować szczególną ostrożność, aby je poufne. W szczególności nie dodawaj plików JSON konta usługi do publicznej kontroli wersji.
Zezwalanie pakietowi Admin SDK na wykrywanie konta usługi
Jeśli Twój kod jest wdrożony w środowisku zarządzanym przez Google, pakiet Admin SDK może spróbować automatycznie wykryć sposób podpisywania tokenów niestandardowych:
Jeśli Twój kod jest wdrożony w standardowym środowisku App Engine w usłudze Java, Python lub Go, pakiet Admin SDK może używać Usługa tożsamości aplikacji dostępnych w tym środowisku do podpisywania tokenów niestandardowych. Usługa tożsamości aplikacji podpisuje dane za pomocą konta usługi udostępnionego przez aplikację Google Wyszukiwarka.
Jeśli Twój kod został wdrożony w innym środowisku zarządzanym (np. Google Cloud) Funkcje, Google Compute Engine), pakiet Firebase Admin SDK może automatycznie wykryć ciąg identyfikatora konta usługi z lokalnego serwer metadanych. Wykryty identyfikator konta usługi jest następnie używany w połączeniu z uprawnieniami do zdalnego podpisywania tokenów.
Aby korzystać z tych metod podpisywania, zainicjuj pakiet SDK w Google Domyślne dane logowania aplikacji i nie określaj ciągu identyfikatora konta usługi:
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();
Aby przetestować ten sam kod lokalnie, pobierz plik JSON konta usługi i ustaw
Zmienna środowiskowa GOOGLE_APPLICATION_CREDENTIALS
wskazująca ją.
Jeśli pakiet SDK Firebase Admin musi wykryć ciąg identyfikatora konta usługi, więc gdy kod tworzy token niestandardowy po raz pierwszy. Wynik jest przechowywany w pamięci podręcznej i używany ponownie podczas kolejnych operacji podpisywania tokenów. Identyfikator automatycznie wykrytego konta usługi jest zwykle jedną z usług domyślnych konta dostarczone przez Google Cloud:
Podobnie jak w przypadku bezpośrednio określonych identyfikatorów kont usługi, usługa automatycznie wykrywana
identyfikatory kont muszą mieć uprawnienie iam.serviceAccounts.signBlob
w przypadku
niestandardowego tokenu. Konieczne może być użycie
Sekcja Administracja
konsoli Google Cloud, aby przyznać domyślne konta usługi
niezbędnych uprawnień. Więcej informacji znajdziesz w sekcji rozwiązywania problemów poniżej.
Używanie identyfikatora konta usługi
Aby zachować spójność między różnymi częściami aplikacji, możesz określ identyfikator konta usługi, którego klucze będą używane do podpisywania tokenów podczas działania w środowisku zarządzanym przez Google. Może to uprościć i zwiększyć bezpieczeństwo zasad uprawnień, a także uniknąć konieczności umieść w kodzie plik JSON konta usługi.
Identyfikator konta usługi znajdziesz w
konsola Google Cloud,
lub w polu client_email
pobranego pliku JSON konta usługi.
Identyfikatory kont usługi to adresy e-mail w tym formacie:
<client-id>@<project-id>.iam.gserviceaccount.com
Identyfikują one jednoznacznie
kont usługi w Firebase i Google Cloud projektach.
Aby utworzyć tokeny niestandardowe przy użyciu osobnego identyfikatora konta usługi, zainicjuj pakiet SDK jak poniżej:
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",
});
Identyfikatory kont usługi nie są informacjami poufnymi, więc ich ujawnienie
jest bez znaczenia. Jednak aby podpisywać tokeny niestandardowe za pomocą określonej usługi
pakiet SDK Firebase Admin musi wywołać usługę zdalną.
Upewnij się też, że konto usługi, do którego jest używany pakiet Admin SDK,
użyj, aby nawiązać to połączenie
– zwykle {project-name}@appspot.gserviceaccount.com
–
ma iam.serviceAccounts.signBlob
uprawnienia.
Więcej informacji znajdziesz w sekcji rozwiązywania problemów poniżej.
Tworzenie tokenów niestandardowych za pomocą pakietu Firebase Admin SDK
Pakiet SDK Firebase Admin ma wbudowaną metodę tworzenia tokenów niestandardowych. Na
minimalnie, musisz podać uid
, który może być dowolnym ciągiem znaków, ale powinien
jednoznacznie identyfikują użytkownika lub urządzenie, które uwierzytelniasz. Te tokeny wygasają
po godzinie.
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
Możesz też opcjonalnie określić dodatkowe roszczenia, które chcesz uwzględnić w niestandardowym
token. Przykładowo poniżej dodano pole premiumAccount
do
token niestandardowy, który będzie dostępny w obiektach auth
/ request.auth
w Regułach zabezpieczeń:
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
Zarezerwowane nazwy tokenów niestandardowych
Logowanie się przy użyciu tokenów niestandardowych na kontach klientów
Po utworzeniu tokena niestandardowego wyślij go do aplikacji klienckiej.
aplikacja kliencka uwierzytelnia się za pomocą tokena niestandardowego przez wywołanie
signInWithCustomToken()
:
iOS+
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;
// ...
});
Jeśli uwierzytelnianie się powiedzie, użytkownik zostanie zalogowany na
aplikacja kliencka z kontem określonym w polu uid
uwzględnionym w niestandardowym
token. Jeśli to konto wcześniej nie istniało, rekord dla tego użytkownika zostanie
Utworzono.
Tak samo jak w przypadku innych metod logowania (np.
signInWithEmailAndPassword()
i signInWithCredential()
) obiekt auth
w Realtime Database Security Rules oraz
obiekt request.auth
w
Cloud Storage Security Rules będzie
zawiera wartość uid
użytkownika. W tym przypadku uid
będzie tym, który
określonego podczas generowania tokena niestandardowego.
Reguły bazy danych
{
"rules": {
"adminContent": {
".read": "auth.uid === 'some-uid'"
}
}
}
Reguły przechowywania
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";
}
}
}
Jeśli token niestandardowy zawiera dodatkowe żądania, można się do nich odwoływać w
auth.token
(Firebase Realtime Database) lub request.auth.token
(Cloud Storage) w regułach:
Reguły bazy danych
{
"rules": {
"premiumContent": {
".read": "auth.token.premiumAccount === true"
}
}
}
Reguły przechowywania
service firebase.storage {
match /b/<your-firebase-storage-bucket>/o {
match /premiumContent/{filename} {
allow read, write: if request.auth.token.premiumAccount == true;
}
}
}
Tworzenie tokenów niestandardowych za pomocą biblioteki JWT innej firmy
Jeśli backend jest w języku, który nie ma oficjalnego administratora Firebase SDK, nadal możesz ręcznie tworzyć tokeny niestandardowe. Po pierwsze, Znajdź zewnętrzną bibliotekę JWT dla swojego języka. Następnie użyj funkcji tę bibliotekę JWT do utworzenia tokena JWT, który zawiera następujące informacje:
Deklaracje tokenów niestandardowych | ||
---|---|---|
alg |
Algorytm | "RS256" |
iss |
Wystawca | Adres e-mail konta usługi projektu |
sub |
Temat | Adres e-mail konta usługi projektu |
aud |
Odbiorcy | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Wystawiony w momencie | Bieżący czas (w sekundach) od początku epoki UNIX |
exp |
Okres ważności |
Czas (w sekundach) od początku epoki systemu UNIX, w którym wygasa token. it
może być maksymalnie 3600 sekund później niż iat .
Uwaga: określa to tylko czas wystąpienia tokenu niestandardowego. wygasa. Gdy jednak zalogujesz się za pomocą signInWithCustomToken() , pozostanie zalogowany(-a) w aplikacji
do czasu unieważnienia sesji lub wylogowania się użytkownika.
|
uid |
Unikalny identyfikator zalogowanego użytkownika musi być ciągiem znaków z zakresu
Długość od 1 do 128 znaków. Krótsze uid są lepsze
skuteczność reklam.
|
|
claims (opcjonalnie) |
Opcjonalne żądania niestandardowe, które mają być uwzględnione w regułach zabezpieczeń auth /
request.auth zmiennych
|
Oto kilka przykładów implementacji tokenów niestandardowych w różne języki, których nie obsługuje pakiet Firebase Admin SDK:
PHP
Przy użyciu 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
Przy użyciu 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
Po utworzeniu tokena niestandardowego wyślij go do aplikacji klienckiej, aby został użyty w: uwierzytelniać się w Firebase. Aby dowiedzieć się, jak to zrobić, zapoznaj się z przykładami powyżej.
Rozwiązywanie problemów
W tej sekcji omawiamy kilka częstych problemów, które deweloperzy mogą napotkać podczas jak tworzyć tokeny niestandardowe i jak z nimi korzystać.
Nie włączono interfejsu IAM API
Jeśli określasz identyfikator konta usługi na potrzeby tokenów podpisywania, możesz otrzymać podobny błąd:
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.
Pakiet Firebase Admin SDK używa IAM API aby podpisywać tokeny. Ten błąd oznacza, że interfejs IAM API nie jest obecnie włączony dla projekt Firebase. Otwórz w przeglądarce link w komunikacie o błędzie, kliknij „Włącz API”. aby włączyć ją w projekcie.
Konto usługi nie ma wymaganych uprawnień
Jeśli na koncie usługi działa pakiet Firebase Admin SDK, który nie ma
iam.serviceAccounts.signBlob
, może pojawić się komunikat o błędzie, taki jak
następujące:
Permission iam.serviceAccounts.signBlob is required to perform this operation on service account projects/-/serviceAccounts/{your-service-account-id}.
Najłatwiejszym sposobem rozwiązania tego problemu jest przyznanie uprawnienia „twórcy tokenów konta usługi”
rolę uprawnień w odniesieniu do danego konta usługi, zwykle
{project-name}@appspot.gserviceaccount.com
:
- Otwórz Administracja. w konsoli Google Cloud.
- Wybierz projekt i kliknij „Dalej”.
- Kliknij ikonę edycji odpowiadającą kontu usługi, które chcesz zaktualizować.
- Kliknij „Dodaj kolejną rolę”.
- Wpisz „Twórca tokenów konta usługi” do filtra wyszukiwania i wybierz z wyników wyszukiwania.
- Kliknij „Zapisz”. aby potwierdzić przypisanie roli.
Zapoznaj się z dokumentacją uprawnień. , aby dowiedzieć się więcej o tym procesie lub jak zaktualizować role za pomocą w narzędziach wiersza poleceń gcloud.
Nie udało się określić konta usługi
Jeśli pojawi się komunikat o błędzie podobny do tego poniżej, oznacza to, że pakiet Firebase Admin SDK nie został poprawnie zainicjowany.
Failed to determine service account ID. Initialize the SDK with service account credentials or specify a service account ID with iam.serviceAccounts.signBlob permission.
Jeśli używasz pakietu SDK do automatycznego wykrywania identyfikatora konta usługi, sprawdź, kod jest wdrażany w zarządzanym środowisku Google z serwerem metadanych. W przeciwnym razie podaj plik JSON konta usługi lub identyfikator konta usługi podczas inicjowania pakietu SDK.