In diesem Artikel erfahren Sie, wie Sie mit externen Identitäten und IAP eine eigene Authentifizierungsseite erstellen. Wenn Sie diese Seite selbst erstellen, Authentifizierungsfluss und User Experience.
Wenn Sie Ihre Benutzeroberfläche nicht vollständig anpassen müssen, IAP hosten Sie eine Anmeldeseite für Sie, oder FirebaseUI für eine optimierte Nutzung verwenden.
Übersicht
So erstellen Sie eine eigene Authentifizierungsseite:
- Aktivieren Sie externe Identitäten. Wählen Sie bei der Einrichtung die Option I'll provide my own UI Option (Ich gebe meine eigene UI-Option) aus.
- Installieren Sie die
gcip-iap
-Bibliothek. - Konfigurieren Sie die Benutzeroberfläche, indem Sie die
AuthenticationHandler
-Benutzeroberfläche implementieren. Ihre Authentifizierungsseite muss die folgenden Szenarien verarbeiten:- Mandantenauswahl
- Nutzerautorisierung
- Nutzeranmeldung
- Fehlerbehandlung
- Optional: Passen Sie Ihre Authentifizierungsseite mit zusätzlichen Funktionen an, z. B. Fortschrittsanzeigen, Abmeldeseiten und Nutzerverarbeitung.
- Testen Sie Ihre UI.
gcip-iap-Bibliothek installieren
Führen Sie den folgenden Befehl aus, um die gcip-iap
-Bibliothek zu installieren:
npm install gcip-iap --save
Das NPM-Modul gcip-iap
abstrahiert die Kommunikation zwischen Ihrer Anwendung, IAP und Identity Platform. So können Sie den gesamten
ohne den zugrunde liegenden Austausch zwischen den beiden Diensten verwalten zu müssen,
UI und IAP.
Verwenden Sie die korrekten Importe für Ihre SDK-Version:
gcip-iap v0.1.4 oder älter
// Import Firebase/GCIP dependencies. These are installed on npm install.
import * as firebase from 'firebase/app';
import 'firebase/auth';
// Import GCIP/IAP module.
import * as ciap from 'gcip-iap';
gcip-iap v1.0.0 bis v1.1.0
Ab Version 1.0.0 erfordert gcip-iap
die Peer-Abhängigkeit firebase
v9 oder höher.
Wenn Sie zu gcip-iap
v1.0.0 oder höher migrieren, führen Sie die folgenden Schritte aus:
Aktionen:
- Aktualisieren Sie die
firebase
-Version in Ihrerpackage.json
-Datei auf Version 9.6.0 oder höher. - Aktualisieren Sie die Importanweisungen für
firebase
so:
// Import Firebase modules.
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
// Import the gcip-iap module.
import * as ciap from 'gcip-iap';
Es sind keine weiteren Codeänderungen erforderlich.
gcip-iap v2.0.0
Ab Version 2.0.0 muss Ihre benutzerdefinierte UI-Anwendung mit dem modularen SDK-Format neu geschrieben werden. Wenn Sie zu gcip-iap
Version 2.0.0 oder höher migrieren, führen Sie die folgenden Aktionen aus:
- Aktualisieren Sie die
firebase
-Version in Ihrerpackage.json
-Datei auf Version 9.8.3 oder höher. - Aktualisieren Sie die Importanweisungen
firebase
so:
// Import Firebase modules.
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider } 'firebase/auth';
// Import the gcip-iap module.
import * as ciap from 'gcip-iap';
Benutzeroberfläche konfigurieren
Erstellen Sie zum Konfigurieren der Benutzeroberfläche eine benutzerdefinierte Klasse, die die
AuthenticationHandler
-Schnittstelle:
interface AuthenticationHandler {
languageCode?: string | null;
getAuth(apiKey: string, tenantId: string | null): FirebaseAuth;
startSignIn(auth: FirebaseAuth, match?: SelectedTenantInfo): Promise<UserCredential>;
selectTenant?(projectConfig: ProjectConfig, tenantIds: string[]): Promise<SelectedTenantInfo>;
completeSignOut(): Promise<void>;
processUser?(user: User): Promise<User>;
showProgressBar?(): void;
hideProgressBar?(): void;
handleError?(error: Error | CIAPError): void;
}
Während der Authentifizierung ruft die Bibliothek automatisch die Methoden von AuthenticationHandler
auf.
Mandanten auswählen
Implementieren Sie selectTenant()
, um einen Mandanten auszuwählen. Ich
können diese Methode implementieren, um einen Mandanten programmatisch auszuwählen, oder
eine UI anzeigen, sodass die Nutzenden selbst eine auswählen können.
In beiden Fällen verwendet die Bibliothek das zurückgegebene SelectedTenantInfo
-Objekt.
um den Authentifizierungsvorgang abzuschließen. Es enthält die ID des ausgewählten Mandanten, alle Anbieter-IDs und die E-Mail-Adresse, die der Nutzer eingegeben hat.
Wenn Sie in Ihrem Projekt mehrere Mandanten haben, müssen Sie einen auswählen, bevor Sie
zum Authentifizieren eines Nutzers. Wenn Sie nur einen einzelnen Mandanten oder die Authentifizierung auf Projektebene verwenden, müssen Sie selectTenant()
nicht implementieren.
IAP unterstützt die gleichen Anbieter wie Identity Platform:
- E-Mail-Adresse und Passwort
- OAuth (Google, Facebook, Twitter, GitHub, Microsoft usw.)
- SAML
- OIDC
- Telefonnummer
- Benutzerdefiniert
- Anonym
Telefonnummer, benutzerdefinierte und anonyme Authentifizierungstypen werden nicht unterstützt für Mehrmandantenfähigkeit.
Mandanten programmatisch auswählen
Nutzen Sie den aktuellen Kontext, um einen Mandanten programmatisch auszuwählen. Die
Die Klasse Authentication
enthält getOriginalURL()
, das den
URL, auf die der Nutzer vor der Authentifizierung zugegriffen hat.
Hiermit können Sie eine Übereinstimmung aus einer Liste der verknüpften Mandanten zu finden:
// Select provider programmatically.
selectTenant(projectConfig, tenantIds) {
return new Promise((resolve, reject) => {
// Show UI to select the tenant.
auth.getOriginalURL()
.then((originalUrl) => {
resolve({
tenantId: getMatchingTenantBasedOnVisitedUrl(originalUrl),
// If associated provider IDs can also be determined,
// populate this list.
providerIds: [],
});
})
.catch(reject);
});
}
Nutzern erlauben, Mieter auszuwählen
Wenn Sie dem Nutzer die Auswahl eines Mandanten ermöglichen möchten, können Sie eine Liste der Mandanten anzeigen lassen, aus der der Nutzer einen auswählen muss, oder Sie fordern den Nutzer auf, seine E-Mail-Adresse einzugeben, um dann eine Übereinstimmung anhand der Domain zu ermitteln:
// Select provider by showing UI.
selectTenant(projectConfig, tenantIds) {
return new Promise((resolve, reject) => {
// Show UI to select the tenant.
renderSelectTenant(
tenantIds,
// On tenant selection.
(selectedTenantId) => {
resolve({
tenantId: selectedTenantId,
// If associated provider IDs can also be determined,
// populate this list.
providerIds: [],
// If email is available, populate this field too.
email: undefined,
});
});
});
}
Nutzer authentifizieren
Nachdem Sie einen Anbieter haben, implementieren Sie getAuth()
, um eine Auth-Instanz zurückzugeben, die dem bereitgestellten API-Schlüssel und der Mandanten-ID entspricht. Wenn keine Mandanten-ID verfügbar ist, müssen Sie stattdessen Identitätsanbieter auf Projektebene verwenden.
getAuth()
verfolgt, wo der Nutzer, der dem
Konfiguration gespeichert. Außerdem ist es damit möglich, das Identity Platform-ID-Token eines zuvor authentifizierten Nutzers im Hintergrund zu aktualisieren, ohne dass der Nutzer seine Anmeldedaten noch einmal eingeben muss.
Wenn Sie mehrere IAP-Ressourcen mit unterschiedlichen Mandanten verwenden, wird empfohlen, für jede Ressource eine eindeutige Authentifizierungsinstanz zu verwenden. Dadurch können Sie mehrere Ressourcen mit unterschiedlichen Konfigurationen die gleiche Authentifizierungsseite nutzen. Außerdem bietet es mehreren Nutzern die Möglichkeit, sich gleichzeitig anzumelden, ohne dass der vorherige Nutzer abgemeldet werden muss.
Im Folgenden finden Sie ein Beispiel für die Implementierung von getAuth()
:
gcip-iap v1.0.0
getAuth(apiKey, tenantId) {
let auth = null;
// Make sure the expected API key is being used.
if (apiKey !== expectedApiKey) {
throw new Error('Invalid project!');
}
try {
auth = firebase.app(tenantId || undefined).auth();
// Tenant ID should be already set on initialization below.
} catch (e) {
// Use different App names for every tenant so that
// multiple users can be signed in at the same time (one per tenant).
const app = firebase.initializeApp(this.config, tenantId || '[DEFAULT]');
auth = app.auth();
// Set the tenant ID on the Auth instance.
auth.tenantId = tenantId || null;
}
return auth;
}
gcip-iap v2.0.0
import {initializeApp, getApp} from 'firebase/app';
import {getAuth} from 'firebase/auth';
getAuth(apiKey, tenantId) {
let auth = null;
// Make sure the expected API key is being used.
if (apiKey !== expectedApiKey) {
throw new Error('Invalid project!');
}
try {
auth = getAuth(getApp(tenantId || undefined));
// Tenant ID should be already set on initialization below.
} catch (e) {
// Use different App names for every tenant so that
// multiple users can be signed in at the same time (one per tenant).
const app = initializeApp(this.config, tenantId || '[DEFAULT]');
auth = getAuth(app);
// Set the tenant ID on the Auth instance.
auth.tenantId = tenantId || null;
}
return auth;
}
Nutzer anmelden
Um die Anmeldung zu verarbeiten, musst du startSignIn()
implementieren und einen
UI, über die sich der Nutzer authentifizieren und anschließend eine
UserCredential
für den angemeldeten Nutzer.
In einer Umgebung mit mehreren Mandanten können Sie die verfügbaren Authentifizierungsmethoden aus SelectedTenantInfo
ermitteln, sofern diese Variable angegeben wurde. Sie enthält die Informationen, die von selectTenant()
zurückgegeben werden.
Das folgende Beispiel zeigt eine startSignIn()
-Implementierung für einen vorhandenen Nutzer mit einer E-Mail-Adresse und einem Passwort:
gcip-iap v1.0.0
startSignIn(auth, selectedTenantInfo) {
return new Promise((resolve, reject) => {
// Show the UI to sign-in or sign-up a user.
$('#sign-in-form').on('submit', (e) => {
const email = $('#email').val();
const password = $('#password').val();
// Example: Ask the user for an email and password.
// Note: The method of sign in may have already been determined from the
// selectedTenantInfo object.
auth.signInWithEmailAndPassword(email, password)
.then((userCredential) => {
resolve(userCredential);
})
.catch((error) => {
// Show the error message.
});
});
});
}
gcip-iap v2.0.0
import {signInWithEmailAndPassword} from 'firebase/auth';
startSignIn(auth, selectedTenantInfo) {
return new Promise((resolve, reject) => {
// Show the UI to sign-in or sign-up a user.
$('#sign-in-form').on('submit', (e) => {
const email = $('#email').val();
const password = $('#password').val();
// Example: Ask the user for an email and password.
// Note: The method of sign in may have already been determined from the
// selectedTenantInfo object.
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
resolve(userCredential);
})
.catch((error) => {
// Show the error message.
});
});
});
}
Sie haben auch die Möglichkeit, Nutzer mit einem Föderationsanbieter wie SAML oder OIDC über ein Pop-up-Fenster oder eine Weiterleitung anzumelden:
gcip-iap v1.0.0
startSignIn(auth, selectedTenantInfo) {
// Show the UI to sign-in or sign-up a user.
return new Promise((resolve, reject) => {
// Provide the user multiple buttons to sign-in.
// For example sign-in with popup using a SAML provider.
// Note: The method of sign in may have already been determined from the
// selectedTenantInfo object.
const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');
auth.signInWithPopup(provider)
.then((userCredential) => {
resolve(userCredential);
})
.catch((error) => {
// Show the error message.
});
// Using redirect flow. When the page redirects back and sign-in completes,
// ciap will detect the result and complete sign-in without any additional
// action.
auth.signInWithRedirect(provider);
});
}
gcip-iap v2.0.0
import {signInWithPopup, SAMLAuthProvider} from 'firebase/auth';
startSignIn(auth, selectedTenantInfo) {
// Show the UI to sign-in or sign-up a user.
return new Promise((resolve, reject) => {
// Provide the user multiple buttons to sign-in.
// For example sign-in with popup using a SAML provider.
// Note: The method of sign in might have already been determined from the
// selectedTenantInfo object.
const provider = new SAMLAuthProvider('saml.myProvider');
signInWithPopup(auth, provider)
.then((userCredential) => {
resolve(userCredential);
})
.catch((error) => {
// Show the error message.
});
// Using redirect flow. When the page redirects back and sign-in completes,
// ciap will detect the result and complete sign-in without any additional
// action.
signInWithRedirect(auth, provider);
});
}
Einige OAuth-Anbieter unterstützen die Übergabe eines Hinweises für die Anmeldung:
gcip-iap v1.0.0
startSignIn(auth, selectedTenantInfo) {
// Show the UI to sign-in or sign-up a user.
return new Promise((resolve, reject) => {
// Use selectedTenantInfo to determine the provider and pass the login hint
// if that provider supports it and the user specified an email address.
if (selectedTenantInfo &&
selectedTenantInfo.providerIds &&
selectedTenantInfo.providerIds.indexOf('microsoft.com') !== -1) {
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.setCustomParameters({
login_hint: selectedTenantInfo.email || undefined,
});
} else {
// Figure out the provider used...
}
auth.signInWithPopup(provider)
.then((userCredential) => {
resolve(userCredential);
})
.catch((error) => {
// Show the error message.
});
});
}
gcip-iap v2.0.0
import {signInWithPopup, OAuthProvider} from 'firebase/auth';
startSignIn(auth, selectedTenantInfo) {
// Show the UI to sign in or sign up a user.
return new Promise((resolve, reject) => {
// Use selectedTenantInfo to determine the provider and pass the login hint
// if that provider supports it and the user specified an email address.
if (selectedTenantInfo &&
selectedTenantInfo.providerIds &&
selectedTenantInfo.providerIds.indexOf('microsoft.com') !== -1) {
const provider = new OAuthProvider('microsoft.com');
provider.setCustomParameters({
login_hint: selectedTenantInfo.email || undefined,
});
} else {
// Figure out the provider used...
}
signInWithPopup(auth, provider)
.then((userCredential) => {
resolve(userCredential);
})
.catch((error) => {
// Show the error message.
});
});
}
Siehe Mit Mehrmandantenfähigkeit authentifizieren .
Fehlerbehebung
Um Nutzern Fehlermeldungen anzuzeigen oder eine Wiederherstellung nach Fehlern wie Netzwerkzeitüberschreitungen zu versuchen,
handleError()
implementieren.
Im folgenden Beispiel wird handleError()
implementiert:
handleError(error) {
showAlert({
code: error.code,
message: error.message,
// Whether to show the retry button. This is only available if the error is
// recoverable via retrial.
retry: !!error.retry,
});
// When user clicks retry, call error.retry();
$('.alert-link').on('click', (e) => {
error.retry();
e.preventDefault();
return false;
});
}
In der folgenden Tabelle sind die IAP-spezifischen Fehlercodes aufgeführt, die
zurückgegeben werden kann. Die Identity Platform kann auch Fehler zurückgeben. finden Sie in der Dokumentation zu
firebase.auth.Auth
Fehlercode | Beschreibung |
---|---|
invalid-argument |
Der Client hat ein ungültiges Argument angegeben. |
failed-precondition |
Die Anfrage kann im aktuellen Systemzustand nicht ausgeführt werden. |
out-of-range |
Der Client hat einen ungültigen Bereich angegeben. |
unauthenticated |
Die Anfrage wurde aufgrund eines fehlenden, ungültigen oder abgelaufenen OAuth-Tokens nicht authentifiziert. |
permission-denied |
Der Client hat keine ausreichende Berechtigungen oder die UI wird in einer nicht autorisierten Domain gehostet. |
not-found |
Die angegebene Ressource wurde nicht gefunden. |
aborted |
Es ist ein Konflikt aufgrund von gleichzeitig ausgeführten Aktionen aufgetreten, beispielsweise ein Read-Modify-Write-Konflikt. |
already-exists |
Die Ressource, die ein Client erstellen möchte, ist bereits vorhanden. |
resource-exhausted |
Es wurde entweder das Ressourcenkontingent überschritten oder das Ratenlimit erreicht. |
cancelled |
Die Anfrage wurde vom Client abgebrochen. |
data-loss |
Es ist ein dauerhafter Datenverlust oder Datenkorruption aufgetreten. |
unknown |
Unbekannter Serverfehler. |
internal |
Interner Serverfehler. |
not-implemented |
Die API-Methode wurde vom Server nicht implementiert. |
unavailable |
Dienst ist nicht verfügbar. |
restart-process |
Sie müssen die URL, über die Sie auf diese Seite weitergeleitet wurden, noch einmal aufrufen und den Authentifizierungsprozess neu starten. |
deadline-exceeded |
Die Frist der Anfrage wurde überschritten. |
authentication-uri-fail |
Authentifizierungs-URI konnte nicht generiert werden. |
gcip-token-invalid |
Ein ungültiges GCIP-ID-Token wurde angegeben. |
gcip-redirect-invalid |
Ungültige Weiterleitungs-URL. |
get-project-mapping-fail |
Fehler beim Abrufen der Projekt-ID. |
gcip-id-token-encryption-error |
Fehler bei der GCIP-ID-Token-Verschlüsselung. |
gcip-id-token-decryption-error |
Fehler bei der Entschlüsselung des GCIP-ID-Tokens. |
gcip-id-token-unescape-error |
Fehler beim Aufheben der Escapezeichen für die websichere Base64-Codierung. |
resource-missing-gcip-sign-in-url |
GCIP-Authentifizierungs-URL für die angegebene IAP-Ressource ist nicht vorhanden. |
Benutzeroberfläche anpassen
Sie können Ihre Authentifizierungsseite mit optionalen Funktionen wie Fortschrittsbalken und Abmeldeseiten.
Fortschrittsanzeige darstellen
So wird dem Nutzer immer dann eine benutzerdefinierte Fortschritts-UI angezeigt, wenn das Modul gcip-iap
lang andauernde Netzwerkaufgaben ausführt:
Implementieren Sie showProgressBar()
und hideProgressBar()
.
Nutzer abmelden
In einigen Fällen kann es sinnvoll sein, Nutzern das Abmelden von allen aktuellen Sitzungen zu erlauben, die die gleiche Authentifizierungs-URL nutzen.
Nachdem sich ein Nutzer abgemeldet hat, gibt es möglicherweise keine URL, zu der er zurückgeleitet werden kann.
Dies ist häufig der Fall, wenn sich ein Nutzer von allen Mandanten abmeldet, die mit einem
. Implementieren Sie in diesem Fall completeSignOut()
,
wird angezeigt, dass der Nutzer sich erfolgreich abgemeldet hat. Wenn Sie diese Methode nicht implementieren,
wird eine leere Seite angezeigt, wenn sich ein Nutzer abmeldet.
Nutzer, die verarbeitet werden
So ändern Sie einen angemeldeten Nutzer vor der Weiterleitung zur IAP-Ressource:
processUser()
implementieren.
Mit dieser Methode können Sie Folgendes tun:
- Mit weiteren Anbietern verknüpfen
- Nutzerprofil aktualisieren
- Nutzer nach der Registrierung zur Eingabe zusätzlicher Daten auffordern
- OAuth-Zugriffstoken verarbeiten, die von
getRedirectResult()
nach dem Aufruf vonsignInWithRedirect()
zurückgegeben werden
Im Folgenden finden Sie ein Beispiel für die Implementierung von processUser()
:
gcip-iap v1.0.0
processUser(user) {
return lastAuthUsed.getRedirectResult().then(function(result) {
// Save additional data, or ask the user for additional profile information
// to store in database, etc.
if (result) {
// Save result.additionalUserInfo.
// Save result.credential.accessToken for OAuth provider, etc.
}
// Return the user.
return user;
});
}
gcip-iap v2.0.0
import {getRedirectResult} from 'firebase/auth';
processUser(user) {
return getRedirectResult(lastAuthUsed).then(function(result) {
// Save additional data, or ask the user for additional profile information
// to store in database, etc.
if (result) {
// Save result.additionalUserInfo.
// Save result.credential.accessToken for OAuth provider, etc.
}
// Return the user.
return user;
});
}
Wenn Änderungen an einem Nutzer in den ID-Token-Anforderungen berücksichtigt werden sollen von IAP an Ihre Anwendung weitergegeben hat, müssen Sie zu aktualisierendes Token:
gcip-iap v1.0.0
processUser(user) {
return user.updateProfile({
photoURL: 'https://example.com/profile/1234/photo.png',
}).then(function() {
// To reflect updated photoURL in the ID token, force token
// refresh.
return user.getIdToken(true);
}).then(function() {
return user;
});
}
gcip-iap v2.0.0
import {updateProfile} from 'firebase/auth';
processUser(user) {
return updateProfile(user, {
photoURL: 'https://example.com/profile/1234/photo.png',
}).then(function() {
// To reflect updated photoURL in the ID token, force token
// refresh.
return user.getIdToken(true);
}).then(function() {
return user;
});
}
UI testen
Nachdem Sie eine Klasse erstellt haben, die AuthenticationHandler
implementiert, können Sie
damit eine neue Authentication
-Instanz erstellt und gestartet wird:
// Implement interface AuthenticationHandler.
// const authHandlerImplementation = ....
const ciapInstance = new ciap.Authentication(authHandlerImplementation);
ciapInstance.start();
Stellen Sie Ihre Anwendung bereit und rufen Sie die Authentifizierungsseite auf. Anschließend sollte Ihre benutzerdefinierte Anmeldungs-UI angezeigt werden.
Nächste Schritte
- Programmatisch auf Ressourcen von Drittanbietern zugreifen
- Sitzungen verwalten
- Weitere Informationen zur Funktionsweise externer Identitäten mit IAP