ब्लॉक करने वाले फ़ंक्शन की मदद से, Firebase से पुष्टि करने की सुविधा को बेहतर बनाएं


ब्लॉकिंग फ़ंक्शन की मदद से, कस्टम कोड को लागू किया जा सकता है. इससे, आपके ऐप्लिकेशन में रजिस्टर करने या साइन इन करने वाले उपयोगकर्ता के नतीजे में बदलाव होता है. उदाहरण के लिए, अगर कोई उपयोगकर्ता कुछ शर्तों को पूरा नहीं करता है, तो उसे पुष्टि करने से रोका जा सकता है. इसके अलावा, क्लाइंट ऐप्लिकेशन को उपयोगकर्ता की जानकारी वापस भेजने से पहले, उसे अपडेट किया जा सकता है.

शुरू करने से पहले

ब्लॉक करने से जुड़े फ़ंक्शन का इस्तेमाल करने के लिए, आपको अपने Firebase प्रोजेक्ट को Firebase Authentication with Identity Platform पर अपग्रेड करना होगा. अगर आपने अब तक अपग्रेड नहीं किया है, तो पहले अपग्रेड करें.

ब्लॉक करने की सुविधा के बारे में जानकारी

इन इवेंट के लिए, ब्लॉक करने की सुविधा रजिस्टर की जा सकती है:

  • उपयोगकर्ता के बनाए जाने से पहले: यह ट्रिगर, नए उपयोगकर्ता को Firebase Authentication डेटाबेस में सेव किए जाने से पहले और आपके क्लाइंट ऐप्लिकेशन को टोकन वापस किए जाने से पहले ट्रिगर होता है.

  • उपयोगकर्ता के साइन इन करने से पहले: यह तब ट्रिगर होता है, जब उपयोगकर्ता के क्रेडेंशियल की पुष्टि हो जाती है. हालांकि, यह Firebase Authentication के आपके क्लाइंट ऐप्लिकेशन को आईडी टोकन भेजने से पहले ट्रिगर होता है. अगर आपका ऐप्लिकेशन, बहु-स्तरीय पुष्टि (एमएफ़ए) की सुविधा का इस्तेमाल करता है, तो यह फ़ंक्शन तब ट्रिगर होता है, जब उपयोगकर्ता दूसरे फ़ैक्टर की पुष्टि कर लेता है. ध्यान दें कि नया उपयोगकर्ता बनाने पर भी, ये दोनों इवेंट ट्रिगर होते हैं.

  • ईमेल भेजने से पहले (सिर्फ़ Node.js के लिए): यह ट्रिगर, किसी उपयोगकर्ता को ईमेल (उदाहरण के लिए,
    साइन-इन या पासवर्ड रीसेट करने का ईमेल) भेजे जाने से पहले ट्रिगर होता है.

  • एसएमएस भेजने से पहले (सिर्फ़ Node.js के लिए): यह फ़ंक्शन, उपयोगकर्ता को एसएमएस भेजे जाने से पहले ट्रिगर होता है. जैसे, मल्टीफ़ैक्टर ऑथेंटिकेशन के मामलों में.

ब्लॉक करने की सुविधाओं का इस्तेमाल करते समय, इन बातों का ध्यान रखें:

  • आपके फ़ंक्शन को सात सेकंड के अंदर जवाब देना होगा. सात सेकंड बाद, Firebase Authentication गड़बड़ी का मैसेज दिखाता है और क्लाइंट का ऑपरेशन पूरा नहीं होता.

  • 200 के अलावा अन्य एचटीटीपी रिस्पॉन्स कोड, आपके क्लाइंट ऐप्लिकेशन को पास किए जाते हैं. पक्का करें कि आपका क्लाइंट कोड, आपके फ़ंक्शन से मिलने वाली किसी भी गड़बड़ी को ठीक कर सके.

  • फ़ंक्शन, आपके प्रोजेक्ट के सभी उपयोगकर्ताओं पर लागू होते हैं. इनमें किरायेदार के तौर पर शामिल उपयोगकर्ता भी शामिल हैं. Firebase Authentication आपके फ़ंक्शन को उपयोगकर्ताओं के बारे में जानकारी देता है. इसमें यह जानकारी भी शामिल होती है कि वे किस किरायेदार से जुड़े हैं, ताकि आप उसके हिसाब से जवाब दे सकें.

  • किसी खाते से किसी अन्य आइडेंटिटी प्रोवाइडर को लिंक करने पर, रजिस्टर किए गए सभी beforeUserSignedIn फ़ंक्शन फिर से ट्रिगर हो जाते हैं.

  • गुमनाम और कस्टम पुष्टि करने से, ब्लॉक करने वाले फ़ंक्शन ट्रिगर नहीं होते.

ब्लॉक करने वाले फ़ंक्शन को डिप्लॉय करना

उपयोगकर्ता की पुष्टि करने के फ़्लो में अपना कस्टम कोड डालने के लिए, ब्लॉकिंग फ़ंक्शन डिप्लॉय करें. ब्लॉक करने की सुविधाएं लागू होने के बाद, पुष्टि करने और उपयोगकर्ता बनाने के लिए, आपके कस्टम कोड का इस्तेमाल सही तरीके से होना चाहिए.

ब्लॉक करने वाले फ़ंक्शन को उसी तरह से डिप्लॉय किया जाता है जिस तरह से किसी फ़ंक्शन को डिप्लॉय किया जाता है. (ज़्यादा जानकारी के लिए, Cloud Functions शुरू करना पेज देखें). सारांश में:

  1. टारगेट किए गए इवेंट को हैंडल करने वाला फ़ंक्शन लिखें.

    उदाहरण के लिए, शुरू करने के लिए, अपने सोर्स में इस तरह का नो-ऑप फ़ंक्शन जोड़ा जा सकता है:

    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
    

    ऊपर दिए गए उदाहरण में, कस्टम ऑथराइज़ेशन लॉजिक को लागू करने के बारे में नहीं बताया गया है. ब्लॉक करने की सुविधा लागू करने का तरीका जानने के लिए, यहां दिए गए सेक्शन देखें. साथ ही, खास उदाहरणों के लिए सामान्य स्थितियां देखें.

  2. Firebase CLI का इस्तेमाल करके, अपने फ़ंक्शन डिप्लॉय करें:

    firebase deploy --only functions
    

    फ़ंक्शन अपडेट करने पर, आपको उन्हें हर बार फिर से डिप्लॉय करना होगा.

उपयोगकर्ता और कॉन्टेक्स्ट की जानकारी पाना

ब्लॉकिंग इवेंट, एक AuthBlockingEvent ऑब्जेक्ट उपलब्ध कराते हैं. इसमें साइन इन करने वाले उपयोगकर्ता के बारे में जानकारी होती है. इन वैल्यू का इस्तेमाल अपने कोड में करें, ताकि यह तय किया जा सके कि किसी ऑपरेशन को आगे बढ़ने की अनुमति देनी है या नहीं.

इस ऑब्जेक्ट में ये प्रॉपर्टी शामिल होती हैं:

नाम ब्यौरा उदाहरण
locale ऐप्लिकेशन की स्थान-भाषा. क्लाइंट एसडीके का इस्तेमाल करके या REST API में स्थानीय भाषा का हेडर पास करके, स्थानीय भाषा सेट की जा सकती है. fr या sv-SE
ipAddress उस डिवाइस का आईपी पता जिससे असली उपयोगकर्ता रजिस्टर कर रहा है या साइन इन कर रहा है. 114.14.200.1
userAgent ब्लॉक करने की सुविधा को ट्रिगर करने वाला उपयोगकर्ता एजेंट. Mozilla/5.0 (X11; Linux x86_64)
eventId इवेंट का यूनीक आइडेंटिफ़ायर. rWsyPtolplG2TBFoOkkgyg
eventType इवेंट का टाइप. इससे इवेंट के नाम की जानकारी मिलती है. जैसे, beforeSignIn या beforeCreate. साथ ही, इससे साइन-इन करने के लिए इस्तेमाल किए गए तरीके की जानकारी मिलती है. जैसे, Google या ईमेल/पासवर्ड. providers/cloud.auth/eventTypes/user.beforeSignIn:password
authType हमेशा USER. USER
resource Firebase Authentication प्रोजेक्ट या किरायेदार. projects/project-id/tenants/tenant-id
timestamp इवेंट ट्रिगर होने का समय. इसे RFC 3339 स्ट्रिंग के तौर पर फ़ॉर्मैट किया जाता है. Tue, 23 Jul 2019 21:10:57 GMT
additionalUserInfo उपयोगकर्ता के बारे में जानकारी देने वाला ऑब्जेक्ट. AdditionalUserInfo
credential उपयोगकर्ता के क्रेडेंशियल के बारे में जानकारी देने वाला ऑब्जेक्ट. AuthCredential

रजिस्ट्रेशन या साइन-इन को ब्लॉक करना

पंजीकरण या साइन-इन करने की कोशिश को ब्लॉक करने के लिए, अपने फ़ंक्शन में HttpsError डालें. उदाहरण के लिए:

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)

आपके पास गड़बड़ी का कस्टम मैसेज तय करने का विकल्प भी है:

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!"
)

यहां दिए गए उदाहरण में, यह दिखाया गया है कि किसी खास डोमेन से बाहर के उपयोगकर्ताओं को आपके ऐप्लिकेशन के लिए रजिस्टर करने से कैसे रोका जा सकता है:

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")

डिफ़ॉल्ट या कस्टम मैसेज का इस्तेमाल करने के बावजूद, Cloud Functions गड़बड़ी को रैप करता है और उसे क्लाइंट को इंटरनल गड़बड़ी के तौर पर दिखाता है. उदाहरण के लिए:

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")

आपके ऐप्लिकेशन को गड़बड़ी का पता लगाना चाहिए और उसके हिसाब से कार्रवाई करनी चाहिए. उदाहरण के लिए:

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.
    }
}

किसी उपयोगकर्ता की भूमिका में बदलाव करना

रजिस्ट्रेशन या साइन-इन करने की कोशिश को ब्लॉक करने के बजाय, ऑपरेशन को जारी रखने की अनुमति दी जा सकती है. हालांकि, User ऑब्जेक्ट में बदलाव किया जा सकता है. यह ऑब्जेक्ट, User के डेटाबेस में सेव होता है और क्लाइंट को वापस भेजा जाता है.Firebase Authentication

किसी उपयोगकर्ता में बदलाव करने के लिए, अपने इवेंट हैंडलर से एक ऐसा ऑब्जेक्ट दिखाएं जिसमें बदलाव किए जाने वाले फ़ील्ड शामिल हों. इन फ़ील्ड में बदलाव किया जा सकता है:

  • displayName
  • disabled
  • emailVerified
  • photoUrl
  • customClaims
  • sessionClaims (सिर्फ़ beforeUserSignedIn)

sessionClaims को छोड़कर, बदले गए सभी फ़ील्ड Firebase Authentication के डेटाबेस में सेव किए जाते हैं. इसका मतलब है कि वे रिस्पॉन्स टोकन में शामिल होते हैं और उपयोगकर्ता के सेशन के बीच बने रहते हैं.

यहां दिए गए उदाहरण में, डिफ़ॉल्ट डिसप्ले नेम सेट करने का तरीका बताया गया है:

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")

अगर आपने beforeUserCreated और beforeUserSignedIn, दोनों के लिए इवेंट हैंडलर रजिस्टर किया है, तो ध्यान दें कि beforeUserCreated के बाद beforeUserSignedIn काम करता है. beforeUserCreated में अपडेट किए गए उपयोगकर्ता फ़ील्ड, beforeUserSignedIn में दिखते हैं. अगर आपने दोनों इवेंट हैंडलर में sessionClaims के अलावा कोई दूसरा फ़ील्ड सेट किया है, तो beforeUserSignedIn में सेट की गई वैल्यू, beforeUserCreated में सेट की गई वैल्यू को बदल देगी. सिर्फ़ sessionClaims के लिए, इन्हें मौजूदा सेशन के टोकन के दावों में शामिल किया जाता है. हालांकि, इन्हें डेटाबेस में सेव नहीं किया जाता.

उदाहरण के लिए, अगर कोई sessionClaims सेट किया गया है, तो beforeUserSignedIn उन्हें beforeUserCreated दावों के साथ दिखाएगा. साथ ही, उन्हें मर्ज कर दिया जाएगा. मर्ज करने पर, अगर sessionClaims में मौजूद कोई कुंजी, customClaims में मौजूद किसी कुंजी से मेल खाती है, तो टोकन के दावों में मेल खाने वाली customClaims को sessionClaims की कुंजी से बदल दिया जाएगा. हालांकि, बदली गई customClaims कुंजी को डेटाबेस में सेव किया जाएगा, ताकि आने वाले समय में किए जाने वाले अनुरोधों के लिए इसका इस्तेमाल किया जा सके.

OAuth क्रेडेंशियल और डेटा के लिए ज़रूरी शर्तें

अलग-अलग पहचान देने वाली कंपनियों से, OAuth क्रेडेंशियल और डेटा को ब्लॉक करने वाले फ़ंक्शन में पास किया जा सकता है. नीचे दी गई टेबल में बताया गया है कि हर आइडेंटिटी प्रोवाइडर के लिए, कौनसे क्रेडेंशियल और डेटा इस्तेमाल किया जा सकता है:

पहचान देने वाली सेवा आईडी टोकन ऐक्सेस टोकन समाप्ति‍ समय टोकन सीक्रेट रीफ़्रेश टोकन साइन-इन करने से जुड़े दावे
Google हां हां हां नहीं हां नहीं
Facebook नहीं हां हां नहीं नहीं नहीं
Twitter नहीं हां नहीं हां नहीं नहीं
GitHub नहीं हां नहीं नहीं नहीं नहीं
Microsoft हां हां हां नहीं हां नहीं
LinkedIn नहीं हां हां नहीं नहीं नहीं
Yahoo हां हां हां नहीं हां नहीं
Apple हां हां हां नहीं हां नहीं
एसएएमएल नहीं नहीं नहीं नहीं नहीं हां
OIDC हां हां हां नहीं हां हां

OAuth टोकन

ब्लॉकिंग फ़ंक्शन में आईडी टोकन, ऐक्सेस टोकन या रीफ़्रेश टोकन का इस्तेमाल करने के लिए, आपको सबसे पहले Firebase कंसोल के ब्लॉकिंग फ़ंक्शन पेज पर मौजूद चेकबॉक्स को चुनना होगा.

OAuth क्रेडेंशियल, जैसे कि आईडी टोकन या ऐक्सेस टोकन का इस्तेमाल करके सीधे तौर पर साइन इन करने पर, पहचान देने वाली कोई भी सेवा रीफ़्रेश टोकन नहीं देगी. इस स्थिति में, क्लाइंट-साइड OAuth क्रेडेंशियल को ब्लॉक करने वाली फ़ंक्शन में पास किया जाएगा.

यहां दिए गए सेक्शन में, हर तरह के आइडेंटिटी प्रोवाइडर के बारे में बताया गया है. साथ ही, उनके साथ काम करने वाले क्रेडेंशियल और डेटा के बारे में भी बताया गया है.

सामान्य ओआईडीसी सेवा देने वाली कंपनियां

जब कोई उपयोगकर्ता सामान्य OIDC सेवा देने वाली कंपनी के साथ साइन इन करता है, तो ये क्रेडेंशियल पास किए जाएंगे:

  • आईडी टोकन: यह तब दिया जाता है, जब id_token फ़्लो चुना जाता है.
  • ऐक्सेस टोकन: यह तब दिया जाता है, जब कोड फ़्लो चुना गया हो. ध्यान दें कि फ़िलहाल, कोड फ़्लो सिर्फ़ REST API के ज़रिए काम करता है.
  • रीफ़्रेश टोकन: यह तब दिया जाता है, जब offline_access स्कोप को चुना गया हो.

उदाहरण:

const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);

Google

जब कोई उपयोगकर्ता Google से साइन इन करता है, तो ये क्रेडेंशियल पास किए जाएंगे:

  • आईडी टोकन
  • ऐक्सेस टोकन
  • रीफ़्रेश टोकन: यह सिर्फ़ तब दिया जाता है, जब इन कस्टम पैरामीटर का अनुरोध किया गया हो:
    • access_type=offline
    • prompt=consent, अगर उपयोगकर्ता ने पहले सहमति दी थी और कोई नया स्कोप नहीं मांगा गया था

उदाहरण:

import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';

const auth = getAuth();
const provider = new GoogleAuthProvider();
provider.setCustomParameters({
  'access_type': 'offline',
  'prompt': 'consent'
});
signInWithPopup(auth, provider);

Google रीफ़्रेश टोकन के बारे में ज़्यादा जानें.

Facebook

जब कोई उपयोगकर्ता Facebook से साइन इन करता है, तो ये क्रेडेंशियल पास किए जाएंगे:

  • ऐक्सेस टोकन: एक ऐक्सेस टोकन वापस भेजा जाता है. इसे दूसरे ऐक्सेस टोकन के बदले में इस्तेमाल किया जा सकता है. Facebook के साथ काम करने वाले अलग-अलग तरह के ऐक्सेस टोकन के बारे में ज़्यादा जानें. साथ ही, यह भी जानें कि उन्हें लंबे समय तक इस्तेमाल किए जा सकने वाले टोकन के लिए कैसे बदला जा सकता है.

GitHub

जब कोई उपयोगकर्ता GitHub से साइन इन करता है, तो ये क्रेडेंशियल पास किए जाएंगे:

  • ऐक्सेस टोकन: यह तब तक मान्य रहता है, जब तक इसे रद्द न कर दिया जाए.

Microsoft

जब कोई उपयोगकर्ता Microsoft खाते से साइन इन करता है, तो ये क्रेडेंशियल पास किए जाएंगे:

  • आईडी टोकन
  • ऐक्सेस टोकन
  • रीफ़्रेश टोकन: अगर offline_access स्कोप चुना जाता है, तो इसे ब्लॉकिंग फ़ंक्शन को पास किया जाता है.

उदाहरण:

import { getAuth, signInWithPopup, OAuthProvider } from 'firebase/auth';

const auth = getAuth();
const provider = new OAuthProvider('microsoft.com');
provider.addScope('offline_access');
signInWithPopup(auth, provider);

Yahoo

जब कोई उपयोगकर्ता Yahoo खाते से साइन इन करता है, तो यहां दिए गए क्रेडेंशियल बिना किसी कस्टम पैरामीटर या स्कोप के पास किए जाएंगे:

  • आईडी टोकन
  • ऐक्सेस टोकन
  • रीफ़्रेश टोकन

LinkedIn

जब कोई उपयोगकर्ता LinkedIn से साइन इन करता है, तो ये क्रेडेंशियल पास किए जाएंगे:

  • ऐक्सेस टोकन

Apple

जब कोई उपयोगकर्ता Apple से साइन इन करता है, तो ये क्रेडेंशियल बिना किसी कस्टम पैरामीटर या स्कोप के पास किए जाएंगे:

  • आईडी टोकन
  • ऐक्सेस टोकन
  • रीफ़्रेश टोकन

सामान्य स्थितियां

यहां कुछ सामान्य उदाहरण दिए गए हैं, जिनसे पता चलता है कि ब्लॉक करने वाले फ़ंक्शन का इस्तेमाल कैसे किया जाता है:

सिर्फ़ किसी खास डोमेन से रजिस्ट्रेशन की अनुमति देना

यहां दिए गए उदाहरण में बताया गया है कि 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",
           )

पुष्टि नहीं किए गए ईमेल पतों वाले उपयोगकर्ताओं को रजिस्टर करने से रोकना

यहां दिए गए उदाहरण में बताया गया है कि बिना पुष्टि किए गए ईमेल पते वाले लोगों को, आपके ऐप्लिकेशन में रजिस्टर करने से कैसे रोका जा सकता है:

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.")

पहचान देने वाली कुछ कंपनियों के ईमेल को पुष्टि किए गए ईमेल के तौर पर माना जाता है

यहां दिए गए उदाहरण में बताया गया है कि कुछ आइडेंटिटी प्रोवाइडर से मिले उपयोगकर्ता के ईमेल पतों को पुष्टि किए गए ईमेल पतों के तौर पर कैसे माना जाता है:

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)

कुछ आईपी पतों से साइन इन करने की सुविधा को ब्लॉक करना

यहां दिए गए उदाहरण में, आईपी पतों की कुछ रेंज से साइन-इन करने की सुविधा को ब्लॉक करने का तरीका बताया गया है:

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.")

कस्टम और सेशन के दावे सेट करना

यहां दिए गए उदाहरण में, कस्टम और सेशन के दावों को सेट करने का तरीका बताया गया है:

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"]
        })

संदिग्ध गतिविधि पर नज़र रखने के लिए, आईपी पतों को ट्रैक करना

किसी उपयोगकर्ता के साइन इन करने के आईपी पते को ट्रैक करके, टोकन की चोरी को रोका जा सकता है. साथ ही, बाद के अनुरोधों पर आईपी पते की तुलना की जा सकती है. अगर अनुरोध संदिग्ध लगता है, जैसे कि आईपी अलग-अलग भौगोलिक क्षेत्रों से हैं, तो उपयोगकर्ता से फिर से साइन इन करने के लिए कहा जा सकता है.

  1. उपयोगकर्ता के साइन इन करने के लिए इस्तेमाल किए गए आईपी पते को ट्रैक करने के लिए, सेशन के दावों का इस्तेमाल करें:

    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})
    
  2. जब कोई उपयोगकर्ता ऐसे संसाधनों को ऐक्सेस करने की कोशिश करता है जिनके लिए Firebase Authentication से पुष्टि करना ज़रूरी होता है, तो अनुरोध में दिए गए आईपी पते की तुलना, साइन इन करने के लिए इस्तेमाल किए गए आईपी पते से करें:

    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)
    

उपयोगकर्ता की फ़ोटो की जांच करना

यहां दिए गए उदाहरण में, उपयोगकर्ताओं की प्रोफ़ाइल फ़ोटो को सुरक्षित करने का तरीका बताया गया है:

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)

इमेज का पता लगाने और उन्हें सुरक्षित करने के तरीके के बारे में ज़्यादा जानने के लिए, Cloud Vision का दस्तावेज़ देखें.

किसी उपयोगकर्ता के आइडेंटिटी प्रोवाइडर के OAuth क्रेडेंशियल ऐक्सेस करना

यहां दिए गए उदाहरण में, Google खाते से साइन इन करने वाले उपयोगकर्ता के लिए रीफ़्रेश टोकन पाने और उसका इस्तेमाल करके Google Calendar API को कॉल करने का तरीका बताया गया है. रीफ़्रेश टोकन को ऑफ़लाइन ऐक्सेस के लिए सेव किया जाता है.

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)

उपयोगकर्ता की कार्रवाई के लिए, reCAPTCHA Enterprise के फ़ैसले को बदलना

यहां दिए गए उदाहरण में, उन उपयोगकर्ता फ़्लो के लिए reCAPTCHA Enterprise के फ़ैसले को बदलने का तरीका बताया गया है जिनके लिए यह सुविधा उपलब्ध है.

reCAPTCHA Enterprise को Firebase Authentication के साथ इंटिग्रेट करने के बारे में ज़्यादा जानने के लिए, reCAPTCHA Enterprise चालू करना लेख पढ़ें.

ब्लॉक करने वाले फ़ंक्शन का इस्तेमाल, कस्टम फ़ैक्टर के आधार पर फ़्लो को अनुमति देने या ब्लॉक करने के लिए किया जा सकता है. इससे 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',
 }
});