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, 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ń:
beforeCreate
: wyzwalany przed zapisaniem nowego użytkownika w bazie danych Firebase Authentication i przed zwróceniem tokena do aplikacji klienckiej.beforeSignIn
: 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 czynnika. Pamiętaj, że utworzenie nowego użytkownika powoduje też wywołanie zdarzeniabeforeSignIn
oprócz zdarzeniabeforeCreate
.beforeEmail
(tylko Node.js): uruchamia się przed wysłaniem do użytkownika e-maila (np.
e-maila z prośbą o zalogowanie się lub zresetowanie hasła).beforeSms
(tylko Node.js): wywoływane 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 wszystkich 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.
beforeSignIn
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 na przykład dodać do
index.js
funkcję bez operacji, 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 functions
Za każdym razem, gdy aktualizujesz funkcje, musisz je ponownie wdrożyć.
Uzyskiwanie informacji o użytkowniku i kontekście
Zdarzenia beforeSignIn
i beforeCreate
dostarczają obiektów User
i EventContext
, które zawierają informacje o użytkowniku logującym się w usłudze. 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 interfejsu API.UserRecord
Obiekt EventContext
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
throw new functions.auth.HttpsError('permission-denied');
W tabeli poniżej znajdziesz listę błędów, które możesz zgłosić, wraz z domyślnymi komunikatami o błędach:
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 |
Brakujący, nieprawidłowy lub wygasły token OAuth. |
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, na przykład konflikt odczytu-modyfikacji-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ż podać niestandardowy komunikat o błędzie:
Node.js
throw new functions.auth.HttpsError('permission-denied', '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
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 domyślnego, czy niestandardowego komunikatu, usługa Cloud Functions opakowuje błąd i zwraca go do klienta jako błąd wewnętrzny. Przykład:
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email user@evil.com}`);
Aplikacja powinna wychwycić błąd i odpowiednio go obsłużyć. 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 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
(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 utrzymują się między sesjami użytkownika.
Poniższy przykład pokazuje, jak ustawić domyślną nazwę wyświetlaną:
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 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 beforeSignIn
zwróci je wraz z wszelkimi roszczeniami beforeCreate
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 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 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 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.
Tokeny odświeżania nie będą zwracane przez żadnych dostawców tożsamości podczas logowania się 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: podawany, jeśli wybrano proces z użyciem 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:
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 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:
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(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
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ż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
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 potwierdzania adresu e-mail podczas rejestracji
Poniższy przykład pokazuje, jak wymagać od użytkownika zweryfikowania adresu e-mail po zarejestrowaniu się:
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 niektórych 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 przykładzie poniżej 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 sesji
Ten przykład pokazuje, jak ustawić roszczenia niestandardowe i roszczenia dotyczące 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 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
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ą 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!' }) }); } }); });
Sprawdzanie zdjęć użytkowników
Poniższy przykład pokazuje, jak oczyścić zdjęcia profilowe 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 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
);
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 wyniku reCAPTCHA Enterprise w przypadku działania użytkownika
Poniższy przykład pokazuje, jak zastąpić wynik 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 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',
}
});