Funkcje blokujące umożliwiają wykonywanie niestandardowego kodu, który modyfikuje wynik rejestracji lub logowania się użytkownika w aplikacji. 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 blokujących, musisz przejść na projekt w Firebase Firebase Authentication with Identity Platform. Jeśli nie masz jeszcze uaktualnionej wersji, najpierw ją uaktualnij.
Omówienie funkcji blokujących
Funkcje blokujące możesz zarejestrować w przypadku tych zdarzeń:
beforeCreate: aktywuje się przed zapisaniem nowego użytkownika w bazie danych Firebase Authentication i przed zwróceniem tokena do aplikacji klienckiej.beforeSignIn: aktywuje się po zweryfikowaniu danych logowania użytkownika, ale zanim Firebase Authentication zwróci token identyfikacji do aplikacji klienckiej. Jeśli aplikacja używa uwierzytelniania wielopoziomowego, funkcja aktywuje się po zweryfikowaniu przez użytkownika drugiego składnika. Pamiętaj, że utworzenie nowego użytkownika powoduje wywołanie nie tylko zdarzeniabeforeCreate, ale teżbeforeSignIn.beforeEmail(tylko Node.js): wywoływana przed wysłaniem e-maila (np. z informacją o logowaniu lub resetowaniu hasła) do użytkownika.beforeSms(tylko Node.js): aktywuje się przed wysłaniem SMS-a do użytkownika, np. w przypadku uwierzytelniania wielopoziomowego.
Podczas korzystania z funkcji blokujących pamiętaj o tych kwestiach:
Funkcja musi odpowiedzieć w ciągu 7 sekund. Po 7 sekundach Firebase Authentication zwraca błąd, a operacja klienta kończy się niepowodzeniem.
Kody odpowiedzi HTTP inne niż
200są 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 wszystkich użytkowników 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 zareagować.
Połączenie innego dostawcy tożsamości z kontem powoduje ponowne uruchomienie wszystkich zarejestrowanych funkcji
beforeSignIn.Uwierzytelnianie anonimowe i niestandardowe nie aktywuje funkcji blokujących.
Wdrażanie funkcji blokującej
Aby wstawić niestandardowy kod do procesów uwierzytelniania użytkowników, wdróż funkcje blokujące. Po wdrożeniu funkcji blokujących kod niestandardowy musi zostać pomyślnie wykonany, aby uwierzytelnianie i tworzenie użytkowników zakończyło się powodzeniem.
Funkcję blokującą wdraża się tak samo jak każdą inną funkcję. (więcej informacji znajdziesz na stronie Pierwsze kroki w Cloud Functions). W skrócie:
Napisz funkcję, która obsługuje zdarzenie docelowe.
Na początek możesz na przykład dodać do pliku
index.jsfunkcję no-op, taką jak ta:const functions = require('firebase-functions/v1'); exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => { // TODO }); The above example has omitted the implementation of custom auth logic. See the following sections to learn how to implement your blocking functions and [Common scenarios](#common-scenarios) for specific examples.
Wdróż funkcje za pomocą interfejsu wiersza poleceń Firebase:
firebase deploy --only functionsPo każdej aktualizacji funkcji musisz je ponownie wdrożyć.
Pobieranie informacji o użytkowniku i kontekście
Zdarzenia beforeSignIn i beforeCreate dostarczają obiekty User i EventContext, które zawierają informacje o logującym się użytkowniku. Użyj tych wartości w kodzie, aby określić, czy zezwolić na wykonanie operacji.
Listę właściwości dostępnych w obiekcie User znajdziesz w dokumentacji API UserRecord.
Obiekt EventContext zawiera te właściwości:
| Nazwa | Opis | Przykład |
|---|---|---|
locale |
Język aplikacji. Ustawienia regionalne możesz skonfigurować za pomocą pakietu SDK klienta lub przekazując nagłówek ustawień regionalnych w interfejsie API REST. | fr lub sv-SE |
ipAddress
| Adres IP urządzenia, z którego użytkownik się rejestruje lub loguje. | 114.14.200.1 |
userAgent
| Klient użytkownika, który wywołuje funkcję blokującą. | Mozilla/5.0 (X11; Linux x86_64) |
eventId
| Unikalny identyfikator zdarzenia. | rWsyPtolplG2TBFoOkkgyg |
eventType
|
Typ zdarzenia. Zawiera informacje o nazwie zdarzenia, np. beforeSignIn lub beforeCreate, oraz powiązanej metodzie logowania, np. Google lub adres e-mail i 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 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, wywołaj HttpsError w funkcji. Na przykład:
Node.js
throw new functions.auth.HttpsError('permission-denied');
W tabeli poniżej znajdziesz błędy, które możesz zgłosić, wraz z domyślnym komunikatem o błędzie:
| Nazwa | Kod | Wiadomość |
|---|---|---|
invalid-argument |
400 |
Klient podał nieprawidłowy argument. |
failed-precondition |
400 |
Żądania nie można wykonać przy aktualnym stanie systemu. |
out-of-range |
400 |
Klient podał nieprawidłowy zakres. |
unauthenticated |
401 |
Brak tokena OAuth, jest on nieprawidłowy lub wygasł. |
permission-denied |
403 |
Klient nie ma wystarczających uprawnień. |
not-found |
404 |
Nie udało się znaleźć podanego zasobu. |
aborted |
409 |
Konflikt równoczesności, np. konflikt odczytu, modyfikacji i zapisu. |
already-exists |
409 |
Zasób, który próbował utworzyć klient, już istnieje. |
resource-exhausted |
429 |
Limit zasobu został wyczerpany lub usługa aktywuje ograniczanie liczby żądań. |
cancelled |
499 |
Żądanie anulowane przez klienta. |
data-loss |
500 |
Nieodwracalna utrata danych lub ich uszkodzenie. |
unknown |
500 |
Nieznany błąd serwera. |
internal |
500 |
Wewnętrzny błąd serwera. |
not-implemented |
501 |
Metoda interfejsu API nie została zaimplementowana przez serwer. |
unavailable |
503 |
Usługa niedostępna |
deadline-exceeded |
504 |
Upłynął termin realizacji żądania. |
Możesz też określić niestandardowy komunikat o błędzie:
Node.js
throw new functions.auth.HttpsError('permission-denied', 'Unauthorized request origin!');
Ten przykład pokazuje, jak zablokować możliwość rejestrowania się w aplikacji użytkownikom, którzy nie należą do określonej domeny:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
// (If the user is authenticating within a tenant context, the tenant ID can be determined from
// user.tenantId or from context.resource, e.g. 'projects/project-id/tenant/tenant-id-1')
// Only users of a specific domain can sign up.
if (user.email.indexOf('@acme.com') === -1) {
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email "${user.email}"`);
}
});
Niezależnie od tego, czy używasz wiadomości domyślnej czy niestandardowej, Cloud Functions opakowuje błąd i zwraca go klientowi jako błąd wewnętrzny. Na przykład:
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email user@evil.com}`);
Aplikacja powinna wykryć błąd i odpowiednio go obsłużyć. Na przykład:
JavaScript
// Blocking functions can also be triggered in a multi-tenant context before user creation.
// firebase.auth().tenantId = 'tenant-id-1';
firebase.auth().createUserWithEmailAndPassword('johndoe@example.com', 'password')
.then((result) => {
result.user.getIdTokenResult()
})
.then((idTokenResult) => {
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 klientowi.
Aby zmodyfikować użytkownika, zwróć z modułu obsługi zdarzeń obiekt zawierający pola do zmodyfikowania. Możesz zmodyfikować te pola:
displayNamedisabledemailVerifiedphotoUrlcustomClaimssessionClaims(tylkobeforeSignIn)
Z wyjątkiem pola sessionClaims wszystkie zmodyfikowane pola są zapisywane w bazie danych Firebase Authentication, co oznacza, że są uwzględniane w tokenie odpowiedzi i zachowywane między sesjami użytkownika.
Poniższy przykład pokazuje, jak ustawić domyślną wyświetlaną nazwę:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
return {
// If no display name is provided, set it to "Guest".
displayName: user.displayName || 'Guest';
};
});
Jeśli zarejestrujesz moduł obsługi zdarzeń zarówno dla beforeCreate, jak i beforeSignIn, pamiętaj, że beforeSignIn jest wykonywany po beforeCreate. Pola użytkowników zaktualizowane w beforeCreate są widoczne w beforeSignIn. Jeśli w obu modułach obsługi zdarzeń ustawisz pole inne niż sessionClaims, wartość ustawiona w beforeSignIn zastąpi wartość ustawioną w beforeCreate. W przypadku sessionClaims są one propagowane do oświadczeń tokena bieżącej sesji, ale nie są utrwalane ani przechowywane w bazie danych.
Jeśli na przykład ustawiono jakieś sessionClaims, beforeSignIn zwróci je wraz z dowolnymi uprawnieniami beforeCreate i zostaną one scalone. Jeśli po scaleniu klucz sessionClaims pasuje do klucza w customClaims, pasujący klucz customClaims zostanie zastąpiony w uprawnieniach tokena przez klucz sessionClaims. Jednak zastąpiony 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 logowania i dane OAuth 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 | Token identyfikacji | Token dostępu | Data ważności | Obiekt tajny tokena | Token odświeżania | Roszczenia dotyczące 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 odświeżania
Aby użyć tokena odświeżania w funkcji blokującej, musisz najpierw zaznaczyć pole wyboru na stronie Funkcje blokujące w konsoli Firebase (otwórz kartę Zabezpieczenia > Uwierzytelnianie > Ustawienia).
Tokeny odświeżania nie będą zwracane przez żadnych dostawców tożsamości podczas logowania się bezpośrednio przy użyciu danych uwierzytelniających OAuth, takich jak token identyfikacji 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 opisano poszczególne typy dostawców tożsamości oraz obsługiwane przez nich dane logowania i dane.
Dostawcy standardowej wersji OIDC
Gdy użytkownik loguje się za pomocą ogólnego dostawcy OIDC, przekazywane są te dane logowania:
- Token identyfikacji: podawany, jeśli wybrany jest przepływ
id_token. - Token dostępu: podawany, jeśli wybrano przepływ kodu. Pamiętaj, że przepływ kodu jest obecnie obsługiwany tylko przez interfejs API typu REST.
- Token odświeżania: podawany, jeśli wybrany jest 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ę przez Google, przekazywane są te dane logowania:
- Token identyfikacji
- Token dostępu
- Token odświeżania: jest podawany tylko wtedy, gdy wymagane są te parametry niestandardowe:
access_type=offlineprompt=consent, jeśli użytkownik wcześniej wyraził zgodę i nie poproszono o nowy zakres
Przykład:
const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
'access_type': 'offline',
'prompt': 'consent'
});
firebase.auth().signInWithPopup(provider);
Dowiedz się więcej o tokenach odświeżania Google.
Gdy użytkownik zaloguje się przez Facebooka, zostaną przekazane 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 wymieniać na tokeny długotrwałe.
GitHub
Gdy użytkownik zaloguje się za pomocą GitHuba, zostaną przekazane te dane logowania:
- Token dostępu: nie wygasa, chyba że zostanie unieważniony.
Microsoft
Gdy użytkownik zaloguje się za pomocą konta Microsoft, zostaną przekazane te dane logowania:
- Token identyfikacji
- Token dostępu
- Token odświeżania: przekazywany do funkcji blokującej, jeśli wybrany jest zakres
offline_access.
Przykład:
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
Yahoo
Gdy użytkownik loguje się za pomocą Yahoo, przekazywane są te dane logowania bez żadnych parametrów niestandardowych ani zakresów:
- Token identyfikacji
- Token dostępu
- Token odświeżania
Gdy użytkownik zaloguje się za pomocą LinkedIn, zostaną przekazane te dane logowania:
- Token dostępu
Apple
Gdy użytkownik loguje się za pomocą Apple, przekazywane są te dane logowania bez żadnych parametrów niestandardowych ani zakresów:
- Token identyfikacji
- Token dostępu
- Token odświeżania
Typowe scenariusze
Oto kilka typowych przypadków użycia funkcji blokujących:
zezwalać na rejestrację tylko z określonej domeny,
Ten przykład pokazuje, jak uniemożliwić użytkownikom, którzy nie należą do domeny example.com, rejestrowanie się w Twojej aplikacji:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (!user.email || user.email.indexOf('@example.com') === -1) {
throw new functions.auth.HttpsError(
'invalid-argument', `Unauthorized email "${user.email}"`);
}
});
Blokowanie rejestracji użytkowników 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
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.email && !user.emailVerified) {
throw new functions.auth.HttpsError(
'invalid-argument', `Unverified email "${user.email}"`);
}
});
wymaganie potwierdzenia adresu e-mail podczas rejestracji,
Poniższy przykład pokazuje, jak wymagać od użytkownika zweryfikowania adresu e-mail po rejestracji:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
const locale = context.locale;
if (user.email && !user.emailVerified) {
// Send custom email verification on sign-up.
return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
return sendCustomVerificationEmail(user.email, link, locale);
});
}
});
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (user.email && !user.emailVerified) {
throw new functions.auth.HttpsError(
'invalid-argument', `"${user.email}" needs to be verified before access is granted.`);
}
});
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 określonych dostawców tożsamości jako zweryfikowane:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.email && !user.emailVerified && context.eventType.indexOf(':facebook.com') !== -1) {
return {
emailVerified: true,
};
}
});
Blokowanie logowania z określonych adresów IP
W tym przykładzie pokazujemy, jak zablokować logowanie z określonych zakresów adresów IP:
Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (isSuspiciousIpAddress(context.ipAddress)) {
throw new functions.auth.HttpsError(
'permission-denied', 'Unauthorized access!');
}
});
Ustawianie deklaracji niestandardowych i deklaracji sesji
Poniższy przykład pokazuje, jak ustawić oświadczenia niestandardowe i oświadczenia sesji:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (context.credential &&
context.credential.providerId === 'saml.my-provider-id') {
return {
// Employee ID does not change so save in persistent claims (stored in
// Auth DB).
customClaims: {
eid: context.credential.claims.employeeid,
},
// Copy role and groups to token claims. These will not be persisted.
sessionClaims: {
role: context.credential.claims.role,
groups: context.credential.claims.groups,
}
}
}
});
śledzenie adresów IP w celu monitorowania podejrzanej aktywności;
Możesz zapobiec kradzieży tokenów, śledząc adres IP, z którego loguje się użytkownik, i porównując go z adresem IP w kolejnych żądaniach. Jeśli żądanie wydaje się podejrzane – na przykład adresy IP pochodzą z różnych regionów geograficznych – możesz poprosić użytkownika o ponowne zalogowanie się.
Użyj deklaracji sesji, aby śledzić adres IP, z którego loguje się użytkownik:
Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { return { sessionClaims: { signInIpAddress: context.ipAddress, }, }; });Gdy użytkownik próbuje uzyskać dostęp do zasobów, które wymagają uwierzytelnienia 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!' }) }); } }); });
Sprawdzanie zdjęć użytkowników
Poniższy przykład pokazuje, jak usunąć informacje ze zdjęć profilowych użytkowników:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
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,
};
}
});
});
Więcej informacji o wykrywaniu i usuwaniu informacji z 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ę przez Google, i użyć go do wywołania interfejsów API Kalendarza Google. 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
);
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (context.credential &&
context.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,
context.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:
// context.additionalUserInfo.profile.granted_scopes (space joined list of scopes).
// Set access token/refresh token.
oAuth2Client.setCredentials({
access_token: context.credential.accessToken,
refresh_token: context.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();
});
});
})
}
});
Zastępowanie werdyktu reCAPTCHA Enterprise w przypadku operacji użytkownika
Poniższy przykład pokazuje, jak zastąpić werdykt reCAPTCHA Enterprise w przypadku obsługiwanych wzorców przeglądania.
Więcej informacji o integrowaniu reCAPTCHA Enterprise z Uwierzytelnianiem Firebase znajdziesz w artykule Włączanie reCAPTCHA Enterprise.
Funkcje blokujące mogą być używane do zezwalania na przepływy lub ich blokowania na podstawie niestandardowych czynników, co zastępuje wynik podany przez reCAPTCHA Enterprise.
Node.js
const functions = require("firebase-functions/v1");
exports.beforesmsv1 = functions.auth.user().beforeSms((context) => {
if (
context.smsType === "SIGN_IN_OR_SIGN_UP" &&
context.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',
}
});