Dzięki funkcjom blokowania możesz uruchamiać niestandardowy kod, który zmienia reakcję aplikacji na zarejestrowanie się lub zalogowanie użytkownika. Możesz na przykład uniemożliwić użytkownikowi uwierzytelnianie się, jeśli nie spełnia on określonych kryteriów, lub zaktualizować informacje o użytkowniku przed ich przekazaniem do aplikacji klienckiej.
Zanim zaczniesz
Aby korzystać z funkcji blokowania, musisz uaktualnić projekt Firebase do wersji Firebase Authentication with Identity Platform. Jeśli jeszcze tego nie zrobisz, najpierw uaktualnij konto.
Funkcje blokowania
Funkcję blokowania możesz zarejestrować w przypadku tych zdarzeń:
Przed utworzeniem użytkownika: uruchamia się, zanim nowy użytkownik zostanie zapisany w bazie danych Firebase Authentication, i zanim token zostanie zwrócony do aplikacji klienckiej.
Przed zalogowaniem użytkownika: funkcja jest wywoływana po zweryfikowaniu danych logowania użytkownika, ale przed Firebase Authentication zwróceniem tokena identyfikacyjnego do aplikacji klienckiej. Jeśli Twoja aplikacja używa uwierzytelniania wielopoziomowego, funkcja jest wywoływana po zweryfikowaniu przez użytkownika drugiego składnika. Pamiętaj, że utworzenie nowego użytkownika powoduje też te 2 zdarzenia.
Przed wysłaniem e-maila (dotyczy tylko Node.js): uruchamia się przed wysłaniem do użytkownika e-maila (np.
e-maila z hasłem do logowania lub do resetowania hasła).Przed wysłaniem wiadomości SMS (tylko Node.js): uruchamia się przed wysłaniem wiadomości SMS do użytkownika, na przykład w przypadku uwierzytelniania wielopoziomowego.
Korzystając z funkcji blokowania, pamiętaj o tych kwestiach:
Funkcja musi odpowiedzieć w ciągu 7 sekund. Po 7 sekundach funkcja Firebase Authentication zwraca błąd, a operacja klienta kończy się niepowodzeniem.
Kody odpowiedzi HTTP inne niż
200
są przekazywane do aplikacji klienckich. Upewnij się, że kod klienta obsługuje wszystkie błędy, które może zwrócić funkcja.Funkcje dotyczą wszystkich użytkowników w projekcie, w tym tych, którzy są w najemcy. Firebase Authentication udostępnia informacje o użytkownikach Twojej funkcji, w tym informacje o tenantach, do których należą, dzięki czemu możesz odpowiednio na nie reagować.
Połączenie innego dostawcy tożsamości z kontem powoduje ponowne uruchomienie wszystkich zarejestrowanych funkcji
beforeUserSignedIn
.Anonimowe i niestandardowe uwierzytelnianie nie powoduje działania funkcji blokowania.
Wdrażanie funkcji blokującej
Aby wstawić kod niestandardowy do procesów uwierzytelniania użytkownika, użyj funkcji blokowania. Gdy funkcje blokowania zostaną wdrożone, niestandardowy kod musi zostać uruchomiony, aby uwierzytelnianie i tworzenie użytkownika przebiegło pomyślnie.
Funkcję blokującą wdraża się tak samo jak każdą inną funkcję. (więcej informacji znajdziesz na stronie Cloud Functions Pierwsze kroki). W skrócie:
Napisz funkcję, która obsłuży wybrane zdarzenie.
Na przykład na początek możesz dodać do źródła funkcję no-op, taką jak ta:
Node.js
import { beforeUserCreated, } from "firebase-functions/v2/identity"; export const beforecreated = beforeUserCreated((event) => { // TODO return; });
Python
@identity_fn.before_user_created() def created_noop(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None: return
W powyższym przykładzie pominięto implementację niestandardowej logiki uwierzytelniania. W następnych sekcjach znajdziesz informacje o tym, jak wdrażać funkcje blokowania, oraz typowe scenariusze z konkretnymi przykładami.
Wdróż funkcje za pomocą interfejsu wiersza poleceń Firebase:
firebase deploy --only functions
Za każdym razem, gdy aktualizujesz funkcje, musisz je ponownie wdrożyć.
Pobieranie informacji o użytkowniku i kontekście
Zdarzenia blokowania udostępniają obiekt AuthBlockingEvent
, który zawiera informacje o logowaniu się użytkownika. Użyj tych wartości w kodze, aby określić, czy operacja ma być kontynuowana.
Obiekt zawiera te właściwości:
Nazwa | Opis | Przykład |
---|---|---|
locale |
Język aplikacji. Możesz ustawić język za pomocą pakietu SDK klienta lub przekazując nagłówek locale w interfejsie REST API. | fr lub sv-SE |
ipAddress
| Adres IP urządzenia, na którym użytkownik rejestruje się lub loguje. | 114.14.200.1 |
userAgent
| Użytkownik agenta wywołujący funkcję blokowania. | Mozilla/5.0 (X11; Linux x86_64) |
eventId
| Unikalny identyfikator zdarzenia. | rWsyPtolplG2TBFoOkkgyg |
eventType
|
Typ zdarzenia. Zawiera ona informacje o nazwie zdarzenia, np. beforeSignIn lub beforeCreate , oraz powiązanej z nim metodzie logowania, np. Google lub e-mail/hasło.
|
providers/cloud.auth/eventTypes/user.beforeSignIn:password
|
authType
| Zawsze USER . |
USER
|
resource
| Projekt lub najemca Firebase Authentication. |
projects/project-id/tenants/tenant-id
|
timestamp
| Czas wywołania zdarzenia sformatowany jako ciąg znaków zgodnie ze specyfikacją RFC 3339. | Tue, 23 Jul 2019 21:10:57 GMT
|
additionalUserInfo
| Obiekt zawierający informacje o użytkowniku. |
AdditionalUserInfo
|
credential
| Obiekt zawierający informacje o danych logowania użytkownika. |
AuthCredential
|
Blokowanie rejestracji lub logowania
Aby zablokować próbę rejestracji lub logowania, użyj funkcji HttpsError
w swojej funkcji. Przykład:
Node.js
import { HttpsError } from "firebase-functions/v2/identity";
throw new HttpsError('invalid-argument');
Python
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT)
Możesz też podać niestandardowy komunikat o błędzie:
Node.js
throw new HttpsError('permission-denied', 'Unauthorized request origin!');
Python (wersja testowa)
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.PERMISSION_DENIED,
message="Unauthorized request origin!"
)
Ten przykład pokazuje, jak zablokować rejestrację w aplikacji użytkownikom spoza określonej domeny:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
// (If the user is authenticating within a tenant context, the tenant ID can be determined from
// user.tenantId or from event.resource, e.g. 'projects/project-id/tenant/tenant-id-1')
// Only users of a specific domain can sign up.
if (!user?.email?.includes('@acme.com')) {
throw new HttpsError('invalid-argument', "Unauthorized email");
}
});
Python
# Block account creation with any non-acme email address.
@identity_fn.before_user_created()
def validatenewuser(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
# User data passed in from the CloudEvent.
user = event.data
# Only users of a specific domain can sign up.
if user.email is None or "@acme.com" not in user.email:
# Return None so that Firebase Auth rejects the account creation.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="Unauthorized email")
Niezależnie od tego, czy używasz komunikatu domyślnego, czy niestandardowego, funkcja Cloud Functions otacza błąd i zwraca go klientowi jako błąd wewnętrzny. Przykład:
Node.js
throw new HttpsError('invalid-argument', "Unauthorized email");
Python
# Only users of a specific domain can sign up.
if user.email is None or "@acme.com" not in user.email:
# Return None so that Firebase Auth rejects the account creation.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="Unauthorized email")
Aplikacja powinna wykryć błąd i odpowiednio go obsłużyć. Przykład:
JavaScript
import { getAuth, createUserWithEmailAndPassword } from 'firebase/auth';
// Blocking functions can also be triggered in a multi-tenant context before user creation.
// firebase.auth().tenantId = 'tenant-id-1';
const auth = getAuth();
try {
const result = await createUserWithEmailAndPassword(auth)
const idTokenResult = await result.user.getIdTokenResult();
console.log(idTokenResult.claim.admin);
} catch(error) {
if (error.code !== 'auth/internal-error' && error.message.indexOf('Cloud Function') !== -1) {
// Display error.
} else {
// Registration succeeds.
}
}
Modyfikowanie użytkownika
Zamiast blokować rejestrację lub próbę zalogowania, możesz zezwolić na kontynuowanie operacji, ale zmodyfikować obiekt User
, który jest zapisywany w bazie danych Firebase Authentication i zwracany do klienta.
Aby zmodyfikować użytkownika, zwracaj obiekt z obsługi zdarzenia zawierający pola, które mają zostać zmodyfikowane. Możesz modyfikować te pola:
displayName
disabled
emailVerified
photoUrl
customClaims
sessionClaims
(tylkobeforeUserSignedIn
)
Poza polem sessionClaims
wszystkie zmodyfikowane pola są zapisywane w bazie danych Firebase Authentication, co oznacza, że są one uwzględniane w tokenie odpowiedzi i pozostają w pamięci między sesjami użytkowników.
Ten przykład pokazuje, jak ustawić domyślną wyświetlaną nazwę:
Node.js
export const beforecreated = beforeUserCreated((event) => {
return {
// If no display name is provided, set it to "Guest".
displayName: event.data.displayName || 'Guest'
};
});
Python
@identity_fn.before_user_created()
def setdefaultname(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
return identity_fn.BeforeCreateResponse(
# If no display name is provided, set it to "Guest".
display_name=event.data.display_name if event.data.display_name is not None else "Guest")
Jeśli zarejestrujesz moduł obsługi zdarzeń zarówno dla beforeUserCreated
, jak i beforeUserSignedIn
, pamiętaj, że beforeUserSignedIn
jest wykonywane po beforeUserCreated
. Pola użytkownika zaktualizowane w beforeUserCreated
są widoczne w beforeUserSignedIn
. Jeśli w obu zdarzeniach ustawisz pole inne niż sessionClaims
, wartość ustawiona w beforeUserSignedIn
zastąpi wartość ustawioną w beforeUserCreated
. Tylko w przypadku sessionClaims
są one propagowane do roszczeń dotyczących tokenów bieżącej sesji, ale nie są przechowywane ani zapisywane w bazie danych.
Jeśli na przykład ustawisz jakiekolwiek wartości sessionClaims
, beforeUserSignedIn
zwróci je wraz z dowolnymi oświadczeniami beforeUserCreated
, które zostaną scalone. Po złączeniu kluczy, jeśli klucz sessionClaims
pasuje do klucza w customClaims
, pasujący klucz customClaims
zostanie zastąpiony w roszczeniach tokena przez klucz sessionClaims
. Jednak nadpisany klucz customClaims
nadal będzie przechowywany w bazie danych na potrzeby przyszłych żądań.
Obsługiwane dane logowania i dane OAuth
Możesz przekazywać dane i dane uwierzytelniające OAuth do funkcji blokowania z różnych dostawców tożsamości. W tabeli poniżej znajdziesz informacje o danych logowania i danych obsługiwanych przez poszczególnych dostawców tożsamości:
Dostawca tożsamości | Identyfikator tokena | Token dostępu | Data ważności | Obiekt tajny tokena | Token odświeżania | Żądania logowania |
---|---|---|---|---|---|---|
Tak | Tak | Tak | Nie | Tak | Nie | |
Nie | Tak | Tak | Nie | Nie | Nie | |
Nie | Tak | Nie | Tak | Nie | Nie | |
GitHub | Nie | Tak | Nie | Nie | Nie | Nie |
Microsoft | Tak | Tak | Tak | Nie | Tak | Nie |
Nie | Tak | Tak | Nie | Nie | Nie | |
Yahoo | Tak | Tak | Tak | Nie | Tak | Nie |
Apple | Tak | Tak | Tak | Nie | Tak | Nie |
SAML | Nie | Nie | Nie | Nie | Nie | Tak |
OIDC | Tak | Tak | Tak | Nie | Tak | Tak |
Tokeny OAuth
Aby używać w funkcji blokowania tokena identyfikacyjnego, tokena dostępu lub tokena odświeżania, musisz najpierw zaznaczyć odpowiednie pole wyboru na stronie Funkcje blokowania w konsoli Firebase.
Żaden dostawca tożsamości nie zwróci tokenów odświeżania podczas logowania się bezpośrednio za pomocą danych logowania OAuth, takich jak token identyfikacyjny lub token dostępu. W tej sytuacji do funkcji blokującej zostaną przekazane te same dane uwierzytelniające OAuth po stronie klienta.
W kolejnych sekcjach opisaliśmy poszczególne typy dostawców tożsamości oraz obsługiwane przez nich dane i uprawnienia.
Dostawcy ogólnej wersji funkcji OIDC
Gdy użytkownik loguje się za pomocą ogólnego dostawcy OIDC, przekazywane są te dane logowania:
- Token tożsamości: jest udostępniany, jeśli wybrano przepływ danych
id_token
. - Token dostępu: podany, jeśli wybrano proces z kodem. Pamiętaj, że obecnie proces ten jest obsługiwany tylko za pomocą interfejsu REST API.
- Token odświeżania: jest dostępny, jeśli wybrano zakres
offline_access
.
Przykład:
const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
Gdy użytkownik loguje się w Google, przekazywane są te dane logowania:
- Token identyfikacyjny
- Token dostępu
- Token odświeżania: jest dostępny tylko wtedy, gdy żądasz tych niestandardowych parametrów:
access_type=offline
prompt=consent
, jeśli użytkownik wyraził już zgodę i nie została przesłana prośba o rozszerzenie zakresu danych
Przykład:
import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
const auth = getAuth();
const provider = new GoogleAuthProvider();
provider.setCustomParameters({
'access_type': 'offline',
'prompt': 'consent'
});
signInWithPopup(auth, provider);
Dowiedz się więcej o tokenach odświeżania Google.
Gdy użytkownik loguje się za pomocą Facebooka, przekazywane są te dane logowania:
- Token dostępu: zwracany jest token dostępu, który można wymienić na inny token dostępu. Dowiedz się więcej o różnych typach tokenów dostępu obsługiwanych przez Facebooka i o tym, jak można je wymienić na tokeny długotrwałe.
GitHub
Gdy użytkownik zaloguje się w GitHub, zostaną przekazane te dane logowania:
- Token dostępu: nie wygasa, chyba że zostanie cofnięty.
Microsoft
Gdy użytkownik loguje się w usłudze Microsoft, przekazywane są te dane logowania:
- Token identyfikacyjny
- Token dostępu
- Token odświeżania: przekazywany do funkcji blokowania, jeśli wybrano zakres
offline_access
.
Przykład:
import { getAuth, signInWithPopup, OAuthProvider } from 'firebase/auth';
const auth = getAuth();
const provider = new OAuthProvider('microsoft.com');
provider.addScope('offline_access');
signInWithPopup(auth, provider);
Yahoo
Gdy użytkownik zaloguje się za pomocą Yahoo, zostaną przekazane te dane logowania bez żadnych parametrów ani zakresów niestandardowych:
- Token identyfikacyjny
- Token dostępu
- Token odświeżania
Gdy użytkownik loguje się za pomocą LinkedIn, przekazywane są te dane logowania:
- Token dostępu
Apple
Gdy użytkownik loguje się za pomocą Apple, przekazywane są te dane logowania bez żadnych parametrów ani zakresów niestandardowych:
- Token identyfikacyjny
- Token dostępu
- Token odświeżania
Typowe scenariusze
Poniższe przykłady pokazują kilka typowych zastosowań funkcji blokowania:
Zezwalanie na rejestrację tylko z konkretnej domeny
Ten przykład pokazuje, jak uniemożliwić użytkownikom spoza domeny
example.com
rejestrowanie się w aplikacji:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (!user?.email?.includes('@example.com')) {
throw new HttpsError(
'invalid-argument', 'Unauthorized email');
}
});
Python (wersja testowa)
@identity_fn.before_user_created()
def validatenewuser(
event: identity_fn.AuthBlockingEvent,
) -> identity_fn.BeforeCreateResponse | None:
# User data passed in from the CloudEvent.
user = event.data
# Only users of a specific domain can sign up.
if user.email is None or "@example.com" not in user.email:
# Return None so that Firebase Auth rejects the account creation.
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="Unauthorized email",
)
Blokowanie rejestracji użytkowników z niezweryfikowanymi adresami e-mail
Ten przykład pokazuje, jak uniemożliwić użytkownikom z niezweryfikowanymi adresami e-mail rejestrowanie się w aplikacji:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (user.email && !user.emailVerified) {
throw new HttpsError(
'invalid-argument', 'Unverified email');
}
});
Python
@identity_fn.before_user_created()
def requireverified(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if event.data.email is not None and not event.data.email_verified:
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message="You must register using a trusted provider.")
traktowanie niektórych e-maili od dostawcy tożsamości jako zweryfikowanych.
Ten przykład pokazuje, jak traktować adresy e-mail użytkowników z pewnych dostawców tożsamości jako zweryfikowane:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (user.email && !user.emailVerified && event.eventType.includes(':facebook.com')) {
return {
emailVerified: true,
};
}
});
Python
@identity_fn.before_user_created()
def markverified(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if event.data.email is not None and "@facebook.com" in event.data.email:
return identity_fn.BeforeSignInResponse(email_verified=True)
Blokowanie logowania z określonych adresów IP
Ten przykład pokazuje, jak zablokować logowanie z określonych zakresów adresów IP:
Node.js
export const beforesignedin = beforeUserSignedIn((event) => {
if (isSuspiciousIpAddress(event.ipAddress)) {
throw new HttpsError(
'permission-denied', 'Unauthorized access!');
}
});
Python
@identity_fn.before_user_signed_in()
def ipban(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeSignInResponse | None:
if is_suspicious(event.ip_address):
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.PERMISSION_DENIED,
message="IP banned.")
Ustawianie roszczeń niestandardowych i roszczeń sesji
Ten przykład pokazuje, jak ustawić oświadczenia niestandardowe i oświadczenia sesji:
Node.js
export const beforecreated = beforeUserCreated((event) => {
if (event.credential &&
event.credential.claims &&
event.credential.providerId === "saml.my-provider-id") {
return {
// Employee ID does not change so save in persistent claims (stored in
// Auth DB).
customClaims: {
eid: event.credential.claims.employeeid,
},
};
}
});
export const beforesignin = beforeUserSignedIn((event) => {
if (event.credential &&
event.credential.claims &&
event.credential.providerId === "saml.my-provider-id") {
return {
// Copy role and groups to token claims. These will not be persisted.
sessionClaims: {
role: event.credential.claims.role,
groups: event.credential.claims.groups,
},
};
}
});
Python
@identity_fn.before_user_created()
def setemployeeid(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if (event.credential is not None and event.credential.claims is not None and
event.credential.provider_id == "saml.my-provider-id"):
return identity_fn.BeforeCreateResponse(
custom_claims={"eid": event.credential.claims["employeeid"]})
@identity_fn.before_user_signed_in()
def copyclaimstosession(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeSignInResponse | None:
if (event.credential is not None and event.credential.claims is not None and
event.credential.provider_id == "saml.my-provider-id"):
return identity_fn.BeforeSignInResponse(session_claims={
"role": event.credential.claims["role"],
"groups": event.credential.claims["groups"]
})
Śledzenie adresów IP w celu monitorowania podejrzanej aktywności
Aby zapobiec kradzieży tokenów, możesz śledzić adres IP, z którego użytkownik się loguje, i porównywać go z adresem IP w kolejnych żądaniach. Jeśli prośba wydaje się podejrzana, np. adresy IP pochodzą z różnych regionów geograficznych, możesz poprosić użytkownika o ponowne zalogowanie się.
Użyj roszczeń sesji, aby śledzić adres IP, z którego użytkownik się loguje:
Node.js
export const beforesignedin = beforeUserSignedIn((event) => { return { sessionClaims: { signInIpAddress: event.ipAddress, }, }; });
Python
@identity_fn.before_user_signed_in() def logip(event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeSignInResponse | None: return identity_fn.BeforeSignInResponse(session_claims={"signInIpAddress": event.ip_address})
Gdy użytkownik próbuje uzyskać dostęp do zasobów, które wymagają uwierzytelniania za pomocą Firebase Authentication, porównaj adres IP w żądaniu z adresem IP użytym do zalogowania:
Node.js
app.post('/getRestrictedData', (req, res) => { // Get the ID token passed. const idToken = req.body.idToken; // Verify the ID token, check if revoked and decode its payload. admin.auth().verifyIdToken(idToken, true).then((claims) => { // Get request IP address const requestIpAddress = req.connection.remoteAddress; // Get sign-in IP address. const signInIpAddress = claims.signInIpAddress; // Check if the request IP address origin is suspicious relative to // the session IP addresses. The current request timestamp and the // auth_time of the ID token can provide additional signals of abuse, // especially if the IP address suddenly changed. If there was a sudden // geographical change in a short period of time, then it will give // stronger signals of possible abuse. if (!isSuspiciousIpAddressChange(signInIpAddress, requestIpAddress)) { // Suspicious IP address change. Require re-authentication. // You can also revoke all user sessions by calling: // admin.auth().revokeRefreshTokens(claims.sub). res.status(401).send({error: 'Unauthorized access. Please login again!'}); } else { // Access is valid. Try to return data. getData(claims).then(data => { res.end(JSON.stringify(data); }, error => { res.status(500).send({ error: 'Server error!' }) }); } }); });
Python (wersja testowa)
from firebase_admin import auth, initialize_app import flask initialize_app() flask_app = flask.Flask(__name__) @flask_app.post() def get_restricted_data(req: flask.Request): # Get the ID token passed. id_token = req.json().get("idToken") # Verify the ID token, check if revoked, and decode its payload. try: claims = auth.verify_id_token(id_token, check_revoked=True) except: return flask.Response(status=500) # Get request IP address. request_ip = req.remote_addr # Get sign-in IP address. signin_ip = claims["signInIpAddress"] # Check if the request IP address origin is suspicious relative to # the session IP addresses. The current request timestamp and the # auth_time of the ID token can provide additional signals of abuse, # especially if the IP address suddenly changed. If there was a sudden # geographical change in a short period of time, then it will give # stronger signals of possible abuse. if is_suspicious_change(signin_ip, request_ip): # Suspicious IP address change. Require re-authentication. # You can also revoke all user sessions by calling: # auth.revoke_refresh_tokens(claims["sub"]) return flask.Response(status=401, response="Unauthorized access. Sign in again!") else: # Access is valid. Try to return data. return data_from_claims(claims)
Sprawdzanie zdjęć użytkowników
Ten przykład pokazuje, jak wygładzić zdjęcia profilowe użytkowników:
Node.js
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (user.photoURL) {
return isPhotoAppropriate(user.photoURL)
.then((status) => {
if (!status) {
// Sanitize inappropriate photos by replacing them with guest photos.
// Users could also be blocked from sign-up, disabled, etc.
return {
photoUrl: PLACEHOLDER_GUEST_PHOTO_URL,
};
}
});
});
Python
@identity_fn.before_user_created()
def sanitizeprofilephoto(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
if event.data.photo_url is not None:
score = analyze_photo_with_ml(event.data.photo_url)
if score > THRESHOLD:
return identity_fn.BeforeCreateResponse(photo_url=PLACEHOLDER_URL)
Więcej informacji o wykrywaniu i czyszczeniu obrazów znajdziesz w dokumentacji Cloud Vision.
Uzyskiwanie dostępu do danych logowania OAuth dostawcy tożsamości użytkownika
Ten przykład pokazuje, jak uzyskać token odświeżania dla użytkownika zalogowanego w Google i użyć go do wywołania interfejsów Google Calendar API. Token odświeżania jest przechowywany na potrzeby dostępu offline.
Node.js
const {OAuth2Client} = require('google-auth-library');
const {google} = require('googleapis');
// ...
// Initialize Google OAuth client.
const keys = require('./oauth2.keys.json');
const oAuth2Client = new OAuth2Client(
keys.web.client_id,
keys.web.client_secret
);
export const beforecreated = beforeUserCreated((event) => {
const user = event.data;
if (event.credential &&
event.credential.providerId === 'google.com') {
// Store the refresh token for later offline use.
// These will only be returned if refresh tokens credentials are included
// (enabled by Cloud console).
return saveUserRefreshToken(
user.uid,
event.credential.refreshToken,
'google.com'
)
.then(() => {
// Blocking the function is not required. The function can resolve while
// this operation continues to run in the background.
return new Promise((resolve, reject) => {
// For this operation to succeed, the appropriate OAuth scope should be requested
// on sign in with Google, client-side. In this case:
// https://www.googleapis.com/auth/calendar
// You can check granted_scopes from within:
// event.additionalUserInfo.profile.granted_scopes (space joined list of scopes).
// Set access token/refresh token.
oAuth2Client.setCredentials({
access_token: event.credential.accessToken,
refresh_token: event.credential.refreshToken,
});
const calendar = google.calendar('v3');
// Setup Onboarding event on user's calendar.
const event = {/** ... */};
calendar.events.insert({
auth: oauth2client,
calendarId: 'primary',
resource: event,
}, (err, event) => {
// Do not fail. This is a best effort approach.
resolve();
});
});
})
}
});
Python
@identity_fn.before_user_created()
def savegoogletoken(
event: identity_fn.AuthBlockingEvent) -> identity_fn.BeforeCreateResponse | None:
"""During sign-up, save the Google OAuth2 access token and queue up a task
to schedule an onboarding session on the user's Google Calendar.
You will only get an access token if you enabled it in your project's blocking
functions settings in the Firebase console:
https://console.firebase.google.com/project/_/authentication/settings
"""
if event.credential is not None and event.credential.provider_id == "google.com":
print(f"Signed in with {event.credential.provider_id}. Saving access token.")
firestore_client: google.cloud.firestore.Client = firestore.client()
doc_ref = firestore_client.collection("user_info").document(event.data.uid)
doc_ref.set({"calendar_access_token": event.credential.access_token}, merge=True)
tasks_client = google.cloud.tasks_v2.CloudTasksClient()
task_queue = tasks_client.queue_path(params.PROJECT_ID.value,
options.SupportedRegion.US_CENTRAL1,
"scheduleonboarding")
target_uri = get_function_url("scheduleonboarding")
calendar_task = google.cloud.tasks_v2.Task(http_request={
"http_method": google.cloud.tasks_v2.HttpMethod.POST,
"url": target_uri,
"headers": {
"Content-type": "application/json"
},
"body": json.dumps({
"data": {
"uid": event.data.uid
}
}).encode()
},
schedule_time=datetime.now() +
timedelta(minutes=1))
tasks_client.create_task(parent=task_queue, task=calendar_task)
Przerywanie decyzji reCAPTCHA Enterprise w przypadku działania użytkownika
Ten przykład pokazuje, jak zastąpić werdykt reCAPTCHA Enterprise w przypadku obsługiwanych przepływów danych użytkownika.
Aby dowiedzieć się więcej o integrowaniu reCAPTCHA Enterprise z usługą uwierzytelniania Firebase, zapoznaj się z artykułem Włączanie reCAPTCHA Enterprise.
Funkcji blokowania można używać do zezwalania na przepływy danych lub ich blokowania na podstawie niestandardowych czynników, co pozwala zastąpić wynik z reCAPTCHA Enterprise.
Node.js
const { beforeSmsSent } = require("firebase-functions/v2/identity");
exports.beforesmssentv2 = beforeSmsSent((event) => {
if (
event.smsType === "SIGN_IN_OR_SIGN_UP" &&
event.additionalUserInfo.phoneNumber.includes('+91')
) {
return {
recaptchaActionOverride: "ALLOW",
};
}
// Allow users to sign in with recaptcha score greater than 0.5
if (event.additionalUserInfo.recaptchaScore > 0.5) {
return {
recaptchaActionOverride: 'ALLOW',
};
}
// Block all others.
return {
recaptchaActionOverride: 'BLOCK',
}
});