ব্লকিং ফাংশন সহ Firebase প্রমাণীকরণ প্রসারিত করুন


ব্লকিং ফাংশন আপনাকে কাস্টম কোড কার্যকর করতে দেয় যা ব্যবহারকারীর নিবন্ধন বা আপনার অ্যাপে সাইন ইন করার ফলাফল পরিবর্তন করে। উদাহরণস্বরূপ, আপনি কোনো ব্যবহারকারীকে প্রমাণীকরণ থেকে আটকাতে পারেন যদি তারা নির্দিষ্ট মানদণ্ড পূরণ না করে, অথবা আপনার ক্লায়েন্ট অ্যাপে ফেরত দেওয়ার আগে ব্যবহারকারীর তথ্য আপডেট করে।

আপনি শুরু করার আগে

ব্লকিং ফাংশন ব্যবহার করার জন্য আপনাকে অবশ্যই আপনার Firebase প্রোজেক্টকে Firebase Authentication with Identity Platform আপগ্রেড করতে হবে। আপনি যদি ইতিমধ্যে আপগ্রেড না করে থাকেন তবে প্রথমে তা করুন।

ব্লকিং ফাংশন বোঝা

আপনি এই ইভেন্টগুলির জন্য ব্লকিং ফাংশন নিবন্ধন করতে পারেন:

  • ব্যবহারকারী তৈরি হওয়ার আগে : Firebase Authentication ডাটাবেসে একটি নতুন ব্যবহারকারী সংরক্ষণ করার আগে এবং আপনার ক্লায়েন্ট অ্যাপে একটি টোকেন ফেরত দেওয়ার আগে ট্রিগার করে।

  • ব্যবহারকারী সাইন ইন করার আগে : ব্যবহারকারীর শংসাপত্র যাচাই করার পরে ট্রিগার হয়, কিন্তু Firebase Authentication আপনার ক্লায়েন্ট অ্যাপে একটি আইডি টোকেন ফেরত দেওয়ার আগে। যদি আপনার অ্যাপ মাল্টি-ফ্যাক্টর প্রমাণীকরণ ব্যবহার করে, ব্যবহারকারী তাদের দ্বিতীয় ফ্যাক্টর যাচাই করার পরে ফাংশনটি ট্রিগার হয়। মনে রাখবেন যে একটি নতুন ব্যবহারকারী তৈরি করা এই উভয় ইভেন্টকে ট্রিগার করে।

  • একটি ইমেল পাঠানোর আগে (শুধুমাত্র Node.js) : একটি ইমেলের আগে ট্রিগার করে (উদাহরণস্বরূপ,
    একটি সাইন-ইন বা পাসওয়ার্ড রিসেট ইমেল) একজন ব্যবহারকারীকে পাঠানো হয়।

  • একটি এসএমএস বার্তা পাঠানোর আগে (শুধুমাত্র Node.js) : মাল্টিফ্যাক্টর প্রমাণীকরণের মতো ক্ষেত্রে ব্যবহারকারীর কাছে একটি SMS বার্তা পাঠানোর আগে ট্রিগার হয়।

ব্লকিং ফাংশন ব্যবহার করার সময় নিম্নলিখিতগুলি মনে রাখবেন:

  • আপনার ফাংশন অবশ্যই 7 সেকেন্ডের মধ্যে প্রতিক্রিয়া জানাতে হবে। 7 সেকেন্ড পরে, Firebase Authentication একটি ত্রুটি ফেরত দেয় এবং ক্লায়েন্ট অপারেশন ব্যর্থ হয়।

  • 200 ছাড়া অন্য HTTP প্রতিক্রিয়া কোডগুলি আপনার ক্লায়েন্ট অ্যাপগুলিতে পাঠানো হয়৷ নিশ্চিত করুন যে আপনার ক্লায়েন্ট কোড আপনার ফাংশন ফেরত দিতে পারে এমন কোনো ত্রুটি পরিচালনা করে।

  • ফাংশনগুলি আপনার প্রকল্পের সমস্ত ব্যবহারকারীর জন্য প্রযোজ্য, যার মধ্যে একটি ভাড়াটে অন্তর্ভুক্ত Firebase Authentication আপনার ফাংশনে ব্যবহারকারীদের সম্পর্কে তথ্য প্রদান করে, তাদের অন্তর্ভুক্ত যেকোন ভাড়াটে সহ, যাতে আপনি সেই অনুযায়ী প্রতিক্রিয়া জানাতে পারেন।

  • অন্য পরিচয় প্রদানকারীকে একটি অ্যাকাউন্টের সাথে লিঙ্ক করা ইউজার সাইনডইন ফাংশনের beforeUserSignedIn নিবন্ধিত যেকোনও পুনরায় ট্রিগার করে।

  • বেনামী এবং কাস্টম প্রমাণীকরণ ব্লকিং ফাংশন ট্রিগার করে না।

একটি ব্লকিং ফাংশন স্থাপন করুন

ব্যবহারকারীর প্রমাণীকরণ প্রবাহে আপনার কাস্টম কোড সন্নিবেশ করতে, ব্লকিং ফাংশন স্থাপন করুন। একবার আপনার ব্লকিং ফাংশন স্থাপন করা হলে, আপনার কাস্টম কোড অবশ্যই সফলভাবে সম্পূর্ণ করতে হবে যাতে প্রমাণীকরণ এবং ব্যবহারকারী তৈরি করা যায়।

আপনি একটি ব্লকিং ফাংশন স্থাপন করেন যেভাবে আপনি যেকোনো ফাংশন স্থাপন করেন। (বিশদ বিবরণের জন্য Cloud Functions শুরু করার পৃষ্ঠাটি দেখুন)। সংক্ষেপে:

  1. লক্ষ্যযুক্ত ইভেন্ট পরিচালনা করে এমন একটি ফাংশন লিখুন।

    উদাহরণস্বরূপ, শুরু করার জন্য, আপনি আপনার উত্সে নিম্নলিখিতগুলির মতো একটি নো-অপ ফাংশন যুক্ত করতে পারেন:

    Node.js

    import {
      beforeUserCreated,
    } from "firebase-functions/v2/identity";
    
    export const beforecreated = beforeUserCreated((event) => {
      // TODO
      return;
    });
    

    পাইথন

    @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 অ্যাপ্লিকেশন লোকেল। আপনি ক্লায়েন্ট SDK ব্যবহার করে লোকেল সেট করতে পারেন, অথবা REST API-তে লোকেল হেডার পাস করে। fr বা sv-SE
ipAddress শেষ ব্যবহারকারী যে ডিভাইস থেকে নিবন্ধন করছেন বা সাইন ইন করছেন তার IP ঠিকানা। 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');

পাইথন

raise https_fn.HttpsError(
    code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT)

আপনি একটি কাস্টম ত্রুটি বার্তাও নির্দিষ্ট করতে পারেন:

Node.js

throw new HttpsError('permission-denied', 'Unauthorized request origin!');

পাইথন (প্রিভিউ)

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

পাইথন

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

পাইথন

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

আপনার অ্যাপের ত্রুটি ধরা উচিত এবং সেই অনুযায়ী এটি পরিচালনা করা উচিত। যেমন:

জাভাস্ক্রিপ্ট

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

একটি ব্যবহারকারী পরিবর্তন

একটি নিবন্ধন বা সাইন-ইন প্রচেষ্টা ব্লক করার পরিবর্তে, আপনি ক্রিয়াকলাপটি চালিয়ে যাওয়ার অনুমতি দিতে পারেন, তবে Firebase Authentication ডাটাবেসে সংরক্ষিত এবং ক্লায়েন্টের কাছে ফিরে আসা User বস্তুটিকে সংশোধন করতে পারেন৷

একজন ব্যবহারকারীকে সংশোধন করতে, আপনার ইভেন্ট হ্যান্ডলার থেকে পরিবর্তন করার জন্য ক্ষেত্রগুলি ধারণকারী একটি বস্তু ফেরত দিন। আপনি নিম্নলিখিত ক্ষেত্রগুলি সংশোধন করতে পারেন:

  • 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'
  };
});

পাইথন

@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 উভয়ের জন্য একটি ইভেন্ট হ্যান্ডলার নিবন্ধন করেন, তাহলে লক্ষ্য করুন যে beforeUserSignedIn beforeUserCreated পরে কার্যকর হয়। beforeUserCreated এ আপডেট করা ব্যবহারকারী ক্ষেত্রগুলি beforeUserSignedIn এ দৃশ্যমান। যদি আপনি উভয় ইভেন্ট হ্যান্ডলারে sessionClaims ছাড়া অন্য কোনো ক্ষেত্র সেট করেন, তাহলে beforeUserSignedIn এ সেট করা মান beforeUserCreated এ সেট করা মানটিকে ওভাররাইট করে। শুধুমাত্র sessionClaims জন্য, সেগুলি বর্তমান সেশনের টোকেন দাবিতে প্রচারিত হয়, কিন্তু ডেটাবেসে স্থায়ী বা সংরক্ষিত হয় না।

উদাহরণস্বরূপ, যদি কোনো sessionClaims সেট করা থাকে, beforeUserSignedIn সেগুলিকে কোনো beforeUserCreated দাবির সাথে ফেরত দেবে এবং সেগুলি একত্রিত হবে। যখন সেগুলি একত্রিত করা হয়, যদি একটি sessionClaims কী customClaims এর একটি কী-এর সাথে মিলে যায়, তাহলে মিলিত customClaims sessionClaims কী দ্বারা টোকেন দাবিতে ওভাররাইট করা হবে৷ যাইহোক, overwitten customClaims কী এখনও ভবিষ্যতের অনুরোধের জন্য ডাটাবেসে টিকে থাকবে।

সমর্থিত OAuth শংসাপত্র এবং ডেটা

আপনি বিভিন্ন পরিচয় প্রদানকারীর থেকে ব্লকিং ফাংশনগুলিতে OAuth শংসাপত্র এবং ডেটা পাস করতে পারেন। নিম্নলিখিত সারণীটি দেখায় যে প্রতিটি পরিচয় প্রদানকারীর জন্য কোন প্রমাণপত্র এবং ডেটা সমর্থিত:

পরিচয় প্রদানকারী আইডি টোকেন অ্যাক্সেস টোকেন মেয়াদ শেষ হওয়ার সময় টোকেন সিক্রেট টোকেন রিফ্রেশ করুন সাইন ইন দাবি
গুগল হ্যাঁ হ্যাঁ হ্যাঁ না হ্যাঁ না
ফেসবুক না হ্যাঁ হ্যাঁ না না না
টুইটার না হ্যাঁ না হ্যাঁ না না
গিটহাব না হ্যাঁ না না না না
মাইক্রোসফট হ্যাঁ হ্যাঁ হ্যাঁ না হ্যাঁ না
লিঙ্কডইন না হ্যাঁ হ্যাঁ না না না
ইয়াহু হ্যাঁ হ্যাঁ হ্যাঁ না হ্যাঁ না
আপেল হ্যাঁ হ্যাঁ হ্যাঁ না হ্যাঁ না
SAML না না না না না হ্যাঁ
ওআইডিসি হ্যাঁ হ্যাঁ হ্যাঁ না হ্যাঁ হ্যাঁ

OAuth টোকেন

একটি ব্লকিং ফাংশনে আইডি টোকেন, অ্যাক্সেস টোকেন বা রিফ্রেশ টোকেন ব্যবহার করতে, আপনাকে প্রথমে Firebase কনসোলের ব্লকিং ফাংশন পৃষ্ঠায় চেকবক্স নির্বাচন করতে হবে।

কোনো আইডি টোকেন বা অ্যাক্সেস টোকেনের মতো OAuth শংসাপত্রের মাধ্যমে সরাসরি সাইন ইন করার সময় কোনো পরিচয় প্রদানকারী দ্বারা রিফ্রেশ টোকেন ফেরত দেওয়া হবে না। এই পরিস্থিতিতে, একই ক্লায়েন্ট-সাইড OAuth শংসাপত্র ব্লকিং ফাংশনে পাস করা হবে।

নিম্নলিখিত বিভাগগুলি প্রতিটি পরিচয় প্রদানকারীর প্রকার এবং তাদের সমর্থিত শংসাপত্র এবং ডেটা বর্ণনা করে।

জেনেরিক OIDC প্রদানকারী

যখন একজন ব্যবহারকারী একটি জেনেরিক 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 এর সাথে সাইন ইন করেন, তখন নিম্নলিখিত শংসাপত্রগুলি পাস করা হবে:

  • আইডি টোকেন
  • অ্যাক্সেস টোকেন
  • রিফ্রেশ টোকেন : নিম্নলিখিত কাস্টম পরামিতি অনুরোধ করা হলে শুধুমাত্র প্রদান করা হয়:
    • 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-এর দ্বারা সমর্থিত বিভিন্ন ধরনের অ্যাক্সেস টোকেন সম্পর্কে আরও জানুন এবং কীভাবে আপনি সেগুলিকে দীর্ঘস্থায়ী টোকেনের জন্য বিনিময় করতে পারেন।

গিটহাব

যখন একজন ব্যবহারকারী GitHub এর সাথে সাইন ইন করে, নিম্নলিখিত শংসাপত্রটি পাস করা হবে:

  • অ্যাক্সেস টোকেন : প্রত্যাহার না হলে মেয়াদ শেষ হয় না।

মাইক্রোসফট

যখন একজন ব্যবহারকারী 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-এর সাথে সাইন ইন করেন, নিম্নলিখিত শংসাপত্রগুলি কোনো কাস্টম প্যারামিটার বা স্কোপ ছাড়াই পাস করা হবে:

  • আইডি টোকেন
  • অ্যাক্সেস টোকেন
  • টোকেন রিফ্রেশ করুন

লিঙ্কডইন

যখন একজন ব্যবহারকারী LinkedIn এর সাথে সাইন ইন করেন, তখন নিম্নলিখিত শংসাপত্রটি পাস করা হবে:

  • অ্যাক্সেস টোকেন

আপেল

যখন একজন ব্যবহারকারী অ্যাপলের সাথে সাইন ইন করেন, তখন নিম্নলিখিত শংসাপত্রগুলি কোনো কাস্টম প্যারামিটার বা স্কোপ ছাড়াই পাস করা হবে:

  • আইডি টোকেন
  • অ্যাক্সেস টোকেন
  • টোকেন রিফ্রেশ করুন

সাধারণ পরিস্থিতি

নিম্নলিখিত উদাহরণগুলি ব্লকিং ফাংশনগুলির জন্য কিছু সাধারণ ব্যবহারের ক্ষেত্রে প্রদর্শন করে:

শুধুমাত্র একটি নির্দিষ্ট ডোমেইন থেকে নিবন্ধনের অনুমতি দেয়

নিম্নলিখিত উদাহরণটি দেখায় যে কীভাবে ব্যবহারকারীরা 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');
  }
});

পাইথন (প্রিভিউ)

 @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');
  }
});

পাইথন

@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,
    };
  }
});

পাইথন

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

নির্দিষ্ট আইপি ঠিকানা থেকে সাইন-ইন ব্লক করা

নিম্নলিখিত উদাহরণ দেখায় কিভাবে নির্দিষ্ট IP ঠিকানা রেঞ্জ থেকে সাইন-ইন ব্লক করতে হয়:

Node.js

export const beforesignedin = beforeUserSignedIn((event) => {
  if (isSuspiciousIpAddress(event.ipAddress)) {
    throw new HttpsError(
      'permission-denied', 'Unauthorized access!');
  }
});

পাইথন

@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,
            },
        };
    }
});

পাইথন

@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,
        },
      };
    });
    

    পাইথন

    @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!' })
          });
        }
      });
    });
    

    পাইথন (প্রিভিউ)

    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,
          };
        }
      });
});

পাইথন

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

কীভাবে চিত্রগুলি সনাক্ত এবং স্যানিটাইজ করবেন সে সম্পর্কে আরও জানতে, ক্লাউড ভিশন ডকুমেন্টেশন দেখুন।

ব্যবহারকারীর পরিচয় প্রদানকারী OAuth শংসাপত্র অ্যাক্সেস করা

নিম্নলিখিত উদাহরণটি দেখায় যে কীভাবে Google-এর সাথে সাইন ইন করা ব্যবহারকারীর জন্য একটি রিফ্রেশ টোকেন পেতে হয় এবং Google ক্যালেন্ডার APIs কল করতে এটি ব্যবহার করে৷ অফলাইন অ্যাক্সেসের জন্য রিফ্রেশ টোকেন সংরক্ষণ করা হয়।

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();
          });
      });
    })
  }
});

পাইথন

@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 এন্টারপ্রাইজের রায় ওভাররাইড করা হচ্ছে

নিম্নলিখিত উদাহরণটি সমর্থিত ব্যবহারকারী প্রবাহের জন্য একটি reCAPTCHA এন্টারপ্রাইজ রায়কে কীভাবে ওভাররাইড করতে হয় তা দেখায়।

Firebase প্রমাণীকরণের সাথে reCAPTCHA এন্টারপ্রাইজ একীভূত করার বিষয়ে আরও জানতে reCAPTCHA Enterprise সক্ষম করুন দেখুন।

ব্লকিং ফাংশনগুলি কাস্টম ফ্যাক্টরগুলির উপর ভিত্তি করে প্রবাহকে অনুমতি দিতে বা ব্লক করতে ব্যবহার করা যেতে পারে, যার ফলে reCAPTCHA এন্টারপ্রাইজ প্রদত্ত ফলাফলকে ওভাররাইড করে।

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',
 }
});