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 uwierzytelnienie, jeśli nie spełnia on określonych kryteriów, lub zaktualizować informacje o użytkowniku przed zwróceniem ich do aplikacji klienckiej.
Zanim zaczniesz
Aby korzystać z funkcji blokowania, musisz przenieść projekt Firebase na abonament Firebase Authentication with Identity Platform. Jeśli jeszcze nie masz konta w wersji premium, najpierw je uaktualnij.
Omówienie funkcji blokujących
Możesz zarejestrować funkcje blokujące dla tych zdarzeń:
Przed utworzeniem użytkownika: wywoływane przed zapisaniem nowego użytkownika w bazie danych Firebase Authentication i przed zwróceniem tokena do aplikacji klienckiej.
Przed zalogowaniem się użytkownika: wywoływana po zweryfikowaniu danych logowania użytkownika, ale przed zwróceniem przez Firebase Authentication tokena identyfikatora do aplikacji klienckiej. Jeśli aplikacja korzysta z uwierzytelniania wielopoziomowego, funkcja jest wywoływana po zweryfikowaniu przez użytkownika drugiego składnika uwierzytelniania. Pamiętaj, że utworzenie nowego użytkownika również wywołuje oba te zdarzenia.
Przed wysłaniem e-maila (tylko Node.js): wywoływany przed wysłaniem do użytkownika e-maila (np.
e-maila z prośbą o zalogowanie się lub zresetowanie hasła).Przed wysłaniem SMS-a (tylko Node.js): wyzwalany przed wysłaniem SMS-a do użytkownika, np. 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.
Do aplikacji klienckich przekazywane są kody odpowiedzi HTTP inne niż
200
. 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 znajdują się w najemcy. Firebase Authentication przekazuje do funkcji informacje o użytkownikach, w tym o najemcach, do których należą, dzięki czemu możesz odpowiednio reagować.
Połączenie innego dostawcy tożsamości z kontem ponownie uruchamia wszystkie zarejestrowane funkcje
beforeUserSignedIn
.Uwierzytelnianie anonimowe i niestandardowe nie powoduje uruchomienia funkcji blokowania.
Wdrażanie funkcji blokującej
Aby wstawić kod niestandardowy do procesów uwierzytelniania użytkowników, wdróż funkcje blokujące. Po wdrożeniu funkcji blokowania niestandardowy kod musi zostać wykonany prawidłowo, aby uwierzytelnianie i tworzenie użytkowników zakończyło się sukcesem.
Funkcję blokującą wdraża się w taki sam sposób jak każdą inną funkcję. (więcej informacji znajdziesz na stronie Cloud Functions Pierwsze kroki). W skrócie:
Napisz funkcję, która obsługuje zdarzenie docelowe.
Na początek możesz dodać do źródła funkcję bez operacji, np. taką:
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 sekcjach poniżej znajdziesz informacje o tym, jak wdrożyć funkcje blokowania, a w sekcji Typowe scenariusze – konkretne przykłady.
Wdróż funkcje za pomocą interfejsu wiersza poleceń Firebase:
firebase deploy --only functions
Za każdym razem, gdy zaktualizujesz funkcje, musisz je ponownie wdrożyć.
Uzyskiwanie informacji o użytkowniku i kontekście
Zdarzenia blokujące udostępniają AuthBlockingEvent
obiekt zawierający informacje o użytkowniku logującym się. Użyj tych wartości w kodzie, aby określić, czy zezwolić na wykonanie operacji.
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 języka w interfejsie REST API. | fr lub sv-SE |
ipAddress
| Adres IP urządzenia, z którego użytkownik rejestruje się lub loguje. | 114.14.200.1 |
userAgent
| Klient użytkownika, który wywołał funkcję blokowania. | Mozilla/5.0 (X11; Linux x86_64) |
eventId
| Unikalny identyfikator wydarzenia. | rWsyPtolplG2TBFoOkkgyg |
eventType
|
Typ zdarzenia. Zawiera informacje o nazwie zdarzenia, np. beforeSignIn lub beforeCreate , oraz powiązanej metodzie logowania, np. Google lub e-mail/hasło.
|
providers/cloud.auth/eventTypes/user.beforeSignIn:password
|
authType
| Zawsze USER . |
USER
|
resource
| Firebase Authentication projekt lub najemca. |
projects/project-id/tenants/tenant-id
|
timestamp
| Czas wywołania zdarzenia w formacie ciągu znaków 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, w funkcji umieść HttpsError
. 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
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.PERMISSION_DENIED,
message="Unauthorized request origin!"
)
Poniższy przykład pokazuje, jak zablokować rejestrację w aplikacji użytkownikom, którzy nie należą do 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 domyślnego, czy niestandardowego komunikatu, funkcja Cloud Functions opakowuje błąd i zwraca go do klienta 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 wychwycić 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ć próbę rejestracji lub logowania, 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, zwróć z funkcji obsługi zdarzeń obiekt zawierający pola do zmodyfikowania. Możesz modyfikować te pola:
displayName
disabled
emailVerified
photoUrl
customClaims
sessionClaims
(tylkobeforeUserSignedIn
)
Z wyjątkiem sessionClaims
wszystkie zmodyfikowane pola są zapisywane w bazie danych Firebase Authentication, co oznacza, że są uwzględniane w tokenie odpowiedzi i utrzymują się między sesjami użytkownika.
Poniższy przykład pokazuje, jak ustawić domyślną nazwę wyświetlaną:
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ń dla obu zdarzeń beforeUserCreated
i beforeUserSignedIn
, pamiętaj, że beforeUserSignedIn
jest wykonywane po beforeUserCreated
. Pola użytkowników zaktualizowane w beforeUserCreated
są widoczne w beforeUserSignedIn
. Jeśli w obu modułach obsługi zdarzeń ustawisz pole inne niż sessionClaims
, wartość ustawiona w beforeUserSignedIn
zastąpi wartość ustawioną w beforeUserCreated
. W przypadku sessionClaims
są one propagowane do roszczeń tokena bieżącej sesji, ale nie są utrwalane ani przechowywane w bazie danych.
Jeśli na przykład ustawiono jakiekolwiek wartości sessionClaims
, funkcja beforeUserSignedIn
zwróci je wraz z wszelkimi roszczeniami beforeUserCreated
i zostaną one scalone. Jeśli po połączeniu klucz sessionClaims
pasuje do klucza w customClaims
, pasujący klucz customClaims
zostanie zastąpiony w deklaracjach tokena przez klucz sessionClaims
. Jednak nadpisany klucz customClaims
będzie nadal przechowywany w bazie danych na potrzeby przyszłych żądań.
Obsługiwane dane logowania i dane OAuth
Możesz przekazywać dane uwierzytelniające OAuth i dane do funkcji blokujących od różnych dostawców tożsamości. W tabeli poniżej znajdziesz informacje o tym, jakie dane logowania i dane są obsługiwane w przypadku 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żyć tokena identyfikatora, tokena dostępu lub tokena odświeżania w funkcji blokującej, musisz najpierw zaznaczyć pole wyboru na stronie Funkcje blokujące w konsoli Firebase.
Tokeny odświeżania nie będą zwracane przez żadnych dostawców tożsamości podczas logowania bezpośrednio za pomocą danych logowania OAuth, takich jak token identyfikatora lub token dostępu. W takiej sytuacji do funkcji blokującej zostaną przekazane te same dane logowania OAuth po stronie klienta.
W sekcjach poniżej znajdziesz opis każdego typu dostawcy tożsamości oraz obsługiwanych przez niego danych logowania i danych.
Dostawcy OIDC
Gdy użytkownik loguje się za pomocą ogólnego dostawcy OIDC, przekazywane są te dane logowania:
- Token identyfikatora: udostępniany, jeśli wybrano przepływ
id_token
. - Token dostępu: jest udostępniany, jeśli wybrano proces kodu. Pamiętaj, że obecnie przepływ kodu jest obsługiwany tylko przez interfejs REST API.
- Token odświeżania: podawany, jeśli wybrano
offline_access
zakres.
Przykład:
const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
Gdy użytkownik loguje się za pomocą Google, przekazywane są te dane logowania:
- Token identyfikatora
- Token dostępu
- Token odświeżania: jest podawany tylko wtedy, gdy zażądano tych parametrów niestandardowych:
access_type=offline
prompt=consent
, jeśli użytkownik wcześniej wyraził zgodę i nie zażądano nowego zakresu.
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żesz je wymienić na tokeny długotrwałe.
GitHub
Gdy użytkownik loguje się za pomocą GitHub, przekazywane są te dane logowania:
- Token dostępu: nie wygasa, chyba że zostanie anulowany.
Microsoft
Gdy użytkownik zaloguje się za pomocą Microsoft, zostaną przekazane te dane logowania:
- Token identyfikatora
- Token dostępu
- Token odświeżania: przekazywany do funkcji blokującej, jeśli wybrano
offline_access
zakres.
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 parametrów niestandardowych ani zakresów:
- Token identyfikatora
- Token dostępu
- Token odświeżania
Gdy użytkownik zaloguje się za pomocą LinkedIn, przekazywane będą te dane logowania:
- Token dostępu
Apple
Gdy użytkownik zaloguje się za pomocą Apple, zostaną przekazane te dane logowania:
- Token identyfikatora
- Token dostępu
- Token odświeżania
Typowe scenariusze
Poniższe przykłady pokazują typowe przypadki użycia funkcji blokujących:
Zezwalanie na rejestrację tylko z określonej domeny
Ten przykład pokazuje, jak uniemożliwić rejestrację w aplikacji użytkownikom, którzy nie należą do domeny example.com
:
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
@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żytkownikom z niezweryfikowanymi adresami e-mail
Poniższy przykład pokazuje, jak uniemożliwić użytkownikom z niezweryfikowanymi adresami e-mail rejestrację 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
Poniższy przykład pokazuje, jak traktować adresy e-mail użytkowników od niektórych 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
Poniższy przykład pokazuje, jak blokować 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 deklaracji niestandardowych i sesji
Ten przykład pokazuje, jak ustawić niestandardowe i sesyjne roszczenia:
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
Możesz zapobiec kradzieży tokena, śledząc adres IP, z którego użytkownik się loguje, i porównując 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żywanym do logowania:
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
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
Poniższy przykład pokazuje, jak oczyścić 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
Poniższy przykład pokazuje, jak uzyskać token odświeżania dla użytkownika, który zalogował się za pomocą Google, i użyć go do wywoływania 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)
Zastępowanie wyniku reCAPTCHA Enterprise w przypadku działania użytkownika
Poniższy przykład pokazuje, jak zastąpić werdykt reCAPTCHA Enterprise w przypadku obsługiwanych ścieżek użytkownika.
Więcej informacji o integrowaniu reCAPTCHA Enterprise z uwierzytelnianiem Firebase znajdziesz w artykule Włączanie reCAPTCHA Enterprise.
Funkcje blokowania można wykorzystać do zezwalania na przepływy lub ich blokowania na podstawie niestandardowych czynników, co spowoduje zastąpienie wyniku podanego przez 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',
}
});