Blocking functions let you execute custom code that modifies the result of a user registering or signing in to your app. For example, you can prevent a user from authenticating if they don't meet certain criteria, or update a user's information before returning it to your client app.
শুরু করার আগে
ব্লকিং ফাংশন ব্যবহার করার জন্য আপনাকে অবশ্যই আপনার ফায়ারবেস প্রজেক্টকে Firebase Authentication with Identity Platform এ আপগ্রেড করতে হবে। যদি আপনি এখনও আপগ্রেড না করে থাকেন, তবে প্রথমে তা করে নিন।
ব্লকিং ফাংশন বোঝা
আপনি এই ইভেন্টগুলির জন্য ব্লকিং ফাংশন নিবন্ধন করতে পারেন:
ব্যবহারকারী তৈরি হওয়ার আগে : নতুন কোনো ব্যবহারকারীকে Firebase Authentication ডেটাবেসে সংরক্ষণ করার আগে এবং আপনার ক্লায়েন্ট অ্যাপে একটি টোকেন ফেরত পাঠানোর আগে এটি সক্রিয় হয়।
ব্যবহারকারী সাইন ইন করার আগে : এটি ব্যবহারকারীর পরিচয়পত্র যাচাই করার পরে, কিন্তু Firebase Authentication আপনার ক্লায়েন্ট অ্যাপে একটি আইডি টোকেন ফেরত পাঠানোর আগে ট্রিগার হয়। যদি আপনার অ্যাপ মাল্টি-ফ্যাক্টর অথেনটিকেশন ব্যবহার করে, তাহলে ব্যবহারকারী তার দ্বিতীয় ফ্যাক্টর যাচাই করার পরে ফাংশনটি ট্রিগার হয়। উল্লেখ্য যে, নতুন ব্যবহারকারী তৈরি করলেও এই দুটি ইভেন্টই ট্রিগার হয়।
ইমেল পাঠানোর আগে (শুধুমাত্র Node.js এর জন্য) : কোনো ব্যবহারকারীকে ইমেল (যেমন, সাইন-ইন বা পাসওয়ার্ড রিসেট ইমেল) পাঠানোর আগে এটি ট্রিগার হয়।
এসএমএস বার্তা পাঠানোর আগে (শুধুমাত্র Node.js এর জন্য) : কোনো ব্যবহারকারীকে এসএমএস বার্তা পাঠানোর আগে এটি ট্রিগার হয়, যেমন মাল্টিফ্যাক্টর অথেনটিকেশনের ক্ষেত্রে।
ব্লকিং ফাংশন ব্যবহার করার সময় নিম্নলিখিত বিষয়গুলো মনে রাখবেন:
আপনার ফাংশনটিকে অবশ্যই ৭ সেকেন্ডের মধ্যে সাড়া দিতে হবে। ৭ সেকেন্ড পর, Firebase Authentication একটি ত্রুটি দেখায় এবং ক্লায়েন্ট অপারেশনটি ব্যর্থ হয়।
200ব্যতীত অন্যান্য HTTP প্রতিক্রিয়া কোড আপনার ক্লায়েন্ট অ্যাপে পাঠানো হয়। আপনার ফাংশন থেকে ফেরত আসতে পারে এমন যেকোনো ত্রুটি যেন আপনার ক্লায়েন্ট কোড সামলাতে পারে, তা নিশ্চিত করুন।ফাংশনগুলো আপনার প্রোজেক্টের সকল ব্যবহারকারীর জন্য প্রযোজ্য, যার মধ্যে কোনো টেন্যান্টের অন্তর্ভুক্ত ব্যবহারকারীরাও রয়েছেন। Firebase Authentication আপনার ফাংশনকে ব্যবহারকারীদের সম্পর্কে তথ্য সরবরাহ করে, যার মধ্যে তারা কোন কোন টেন্যান্টের অন্তর্ভুক্ত তাও থাকে, যাতে আপনি সেই অনুযায়ী সাড়া দিতে পারেন।
কোনো অ্যাকাউন্টের সাথে অন্য কোনো পরিচয় প্রদানকারীকে লিঙ্ক করলে,
beforeUserSignedInফাংশন পুনরায় সক্রিয় হয়ে যায়।বেনামী এবং কাস্টম প্রমাণীকরণ ব্লকিং ফাংশন সক্রিয় করে না।
একটি ব্লকিং ফাংশন স্থাপন করুন
ব্যবহারকারী প্রমাণীকরণ ফ্লো-তে আপনার কাস্টম কোড অন্তর্ভুক্ত করতে, ব্লকিং ফাংশনগুলো ডিপ্লয় করুন। আপনার ব্লকিং ফাংশনগুলো ডিপ্লয় করা হয়ে গেলে, প্রমাণীকরণ এবং ব্যবহারকারী তৈরি সফল হওয়ার জন্য আপনার কাস্টম কোডটি অবশ্যই সফলভাবে সম্পন্ন হতে হবে।
যেকোনো ফাংশন যেভাবে স্থাপন করা হয়, ঠিক সেভাবেই একটি ব্লকিং ফাংশনও স্থাপন করতে হয়। (বিস্তারিত জানতে Cloud Functions গেটিং স্টার্টেড পেজটি দেখুন)। সংক্ষেপে:
একটি ফাংশন লিখুন যা নির্দিষ্ট ইভেন্টটি পরিচালনা করবে।
উদাহরণস্বরূপ, শুরু করার জন্য, আপনি আপনার সোর্সে নিম্নলিখিতের মতো একটি নো-অপ ফাংশন যোগ করতে পারেন:
নোড.জেএস
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উপরের উদাহরণটিতে কাস্টম অথেন্টিকেশন লজিকের প্রয়োগ বাদ দেওয়া হয়েছে। আপনার ব্লকিং ফাংশনগুলো কীভাবে প্রয়োগ করবেন তা জানতে নিম্নলিখিত বিভাগগুলো এবং নির্দিষ্ট উদাহরণের জন্য ‘সাধারণ পরিস্থিতি’ (Common scenarios) দেখুন।
Deploy your functions using the Firebase CLI:
firebase deploy --only functionsপ্রতিবার ফাংশন আপডেট করার সময় আপনাকে অবশ্যই সেগুলো পুনরায় ডিপ্লয় করতে হবে।
ব্যবহারকারী এবং প্রাসঙ্গিক তথ্য পাওয়া
ব্লকিং ইভেন্টগুলো একটি AuthBlockingEvent অবজেক্ট প্রদান করে, যাতে সাইন ইন করা ব্যবহারকারীর তথ্য থাকে। কোনো অপারেশনকে এগিয়ে যেতে দেওয়া হবে কিনা, তা নির্ধারণ করতে আপনার কোডে এই মানগুলো ব্যবহার করুন।
অবজেক্টটিতে নিম্নলিখিত প্রোপার্টিগুলো রয়েছে:
| নাম | বর্ণনা | উদাহরণ |
|---|---|---|
locale | অ্যাপ্লিকেশন লোকেল। আপনি ক্লায়েন্ট SDK ব্যবহার করে, অথবা REST API-তে লোকেল হেডার পাস করে লোকেল সেট করতে পারেন। | fr অথবা sv-SE |
ipAddress | যে ডিভাইস থেকে ব্যবহারকারী নিবন্ধন বা সাইন ইন করছেন, সেটির আইপি অ্যাড্রেস। | 114.14.200.1 |
userAgent | ব্যবহারকারী এজেন্ট ব্লকিং ফাংশনটি সক্রিয় করছে। | Mozilla/5.0 (X11; Linux x86_64) |
eventId | ঘটনাটির অনন্য শনাক্তকারী। | rWsyPtolplG2TBFoOkkgyg |
eventType | ইভেন্টের ধরণ। এটি ইভেন্টের নাম, যেমন beforeSignIn বা beforeCreate , এবং ব্যবহৃত সংশ্লিষ্ট সাইন-ইন পদ্ধতি, যেমন গুগল বা ইমেল/পাসওয়ার্ড, সম্পর্কে তথ্য প্রদান করে। | 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 | An object containing information about the user. | AdditionalUserInfo |
credential | ব্যবহারকারীর পরিচয়পত্র সম্পর্কিত তথ্য ধারণকারী একটি অবজেক্ট। | AuthCredential |
নিবন্ধন বা সাইন-ইন ব্লক করা হচ্ছে
রেজিস্ট্রেশন বা সাইন-ইন করার চেষ্টা ব্লক করতে, আপনার ফাংশনে একটি HttpsError থ্রো করুন। উদাহরণস্বরূপ:
নোড.জেএস
import { HttpsError } from "firebase-functions/v2/identity";
throw new HttpsError('invalid-argument');
পাইথন
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT)
আপনি একটি নিজস্ব ত্রুটির বার্তাও নির্দিষ্ট করতে পারেন:
নোড.জেএস
throw new HttpsError('permission-denied', 'Unauthorized request origin!');
পাইথন
raise https_fn.HttpsError(
code=https_fn.FunctionsErrorCode.PERMISSION_DENIED,
message="Unauthorized request origin!"
)
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি নির্দিষ্ট ডোমেইনের বাইরের ব্যবহারকারীদের আপনার অ্যাপে নিবন্ধন করা থেকে ব্লক করা যায়:
নোড.জেএস
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 ত্রুটিটিকে একটি অভ্যন্তরীণ ত্রুটি হিসাবে ক্লায়েন্টের কাছে ফেরত পাঠায়। উদাহরণস্বরূপ:
নোড.জেএস
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 এর ডেটাবেসে সংরক্ষিত হয়, যার অর্থ হল সেগুলি রেসপন্স টোকেনে অন্তর্ভুক্ত থাকে এবং ব্যবহারকারীর সেশনগুলির মধ্যে স্থায়ী হয়।
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি ডিফল্ট ডিসপ্লে নাম সেট করতে হয়:
নোড.জেএস
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")
If you register an event handler for both beforeUserCreated and beforeUserSignedIn , note that beforeUserSignedIn executes after beforeUserCreated . User fields updated in beforeUserCreated are visible in beforeUserSignedIn . If you set a field other than sessionClaims in both event handlers, the value set in beforeUserSignedIn overwrites the value set in beforeUserCreated . For sessionClaims only, they are propagated to the current session's token claims, but are not persisted or stored in the database.
উদাহরণস্বরূপ, যদি কোনো sessionClaims সেট করা থাকে, তাহলে beforeUserSignedIn সেগুলোকে যেকোনো beforeUserCreated ক্লেইমের সাথে রিটার্ন করবে এবং সেগুলোকে মার্জ করা হবে। যখন সেগুলোকে মার্জ করা হয়, যদি একটি sessionClaims কী customClaims এর কোনো কী-এর সাথে মিলে যায়, তাহলে টোকেন ক্লেইমস-এ মিলে যাওয়া customClaims টি sessionClaims কী দ্বারা ওভাররাইট হয়ে যাবে। তবে, ওভাররাইট হয়ে যাওয়া customClaims কী-টি ভবিষ্যতের রিকোয়েস্টের জন্য ডাটাবেসে সংরক্ষিত থাকবে।
সমর্থিত OAuth পরিচয়পত্র এবং ডেটা
আপনি বিভিন্ন আইডেন্টিটি প্রোভাইডারের ব্লকিং ফাংশনগুলিতে OAuth ক্রেডেনশিয়াল এবং ডেটা পাস করতে পারেন। নিম্নলিখিত সারণিতে দেখানো হয়েছে যে প্রতিটি আইডেন্টিটি প্রোভাইডারের জন্য কোন ক্রেডেনশিয়াল এবং ডেটা সমর্থিত:
| পরিচয় প্রদানকারী | আইডি টোকেন | অ্যাক্সেস টোকেন | মেয়াদ শেষ হওয়ার সময় | টোকেন গোপনীয়তা | রিফ্রেশ টোকেন | সাইন-ইন দাবি |
|---|---|---|---|---|---|---|
| গুগল | হ্যাঁ | হ্যাঁ | হ্যাঁ | না | হ্যাঁ | না |
| ফেসবুক | না | হ্যাঁ | হ্যাঁ | না | না | না |
| টুইটার | না | হ্যাঁ | না | হ্যাঁ | না | না |
| গিটহাব | না | হ্যাঁ | না | না | না | না |
| মাইক্রোসফট | হ্যাঁ | হ্যাঁ | হ্যাঁ | না | হ্যাঁ | না |
| লিঙ্কডইন | না | হ্যাঁ | হ্যাঁ | না | না | না |
| ইয়াহু | হ্যাঁ | হ্যাঁ | হ্যাঁ | না | হ্যাঁ | না |
| আপেল | হ্যাঁ | হ্যাঁ | হ্যাঁ | না | হ্যাঁ | না |
| স্যামল | না | না | না | না | না | হ্যাঁ |
| ওআইডিসি | হ্যাঁ | হ্যাঁ | হ্যাঁ | না | হ্যাঁ | হ্যাঁ |
OAuth টোকেন
কোনো ব্লকিং ফাংশনে আইডি টোকেন, অ্যাক্সেস টোকেন বা রিফ্রেশ টোকেন ব্যবহার করতে হলে, আপনাকে প্রথমে Firebase কনসোলের 'ব্লকিং ফাংশনস' পেজে থাকা চেকবক্সটি সিলেক্ট করতে হবে।
আইডি টোকেন বা অ্যাক্সেস টোকেনের মতো কোনো OAuth ক্রেডেনশিয়াল দিয়ে সরাসরি সাইন ইন করার সময় কোনো আইডেন্টিটি প্রোভাইডারই রিফ্রেশ টোকেন ফেরত দেবে না। এই পরিস্থিতিতে, একই ক্লায়েন্ট-সাইড OAuth ক্রেডেনশিয়ালটি ব্লকিং ফাংশনে পাঠানো হবে।
নিম্নলিখিত বিভাগগুলিতে প্রতিটি পরিচয় প্রদানকারীর প্রকার এবং তাদের দ্বারা সমর্থিত প্রমাণপত্র ও ডেটা বর্ণনা করা হয়েছে।
জেনেরিক OIDC প্রদানকারী
যখন কোনো ব্যবহারকারী একটি জেনেরিক OIDC প্রোভাইডার দিয়ে সাইন ইন করেন, তখন নিম্নলিখিত ক্রেডেনশিয়ালগুলো প্রদান করা হবে:
- আইডি টোকেন :
id_tokenফ্লো নির্বাচন করা হলে এটি প্রদান করা হয়। - অ্যাক্সেস টোকেন : কোড ফ্লো নির্বাচন করা হলে এটি প্রদান করা হয়। উল্লেখ্য যে, কোড ফ্লো বর্তমানে শুধুমাত্র REST API-এর মাধ্যমে সমর্থিত।
- Refresh token : Provided if the
offline_accessscope is selected.
উদাহরণ:
const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
গুগল
যখন কোনো ব্যবহারকারী গুগল দিয়ে সাইন ইন করবেন, তখন নিম্নলিখিত পরিচয়পত্রগুলো প্রদান করা হবে:
- আইডি টোকেন
- অ্যাক্সেস টোকেন
- রিফ্রেশ টোকেন : শুধুমাত্র তখনই প্রদান করা হবে, যদি নিম্নলিখিত কাস্টম প্যারামিটারগুলির জন্য অনুরোধ করা হয়:
-
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);
গুগল রিফ্রেশ টোকেন সম্পর্কে আরও জানুন।
ফেসবুক
যখন কোনো ব্যবহারকারী ফেসবুক দিয়ে সাইন ইন করবেন, তখন নিম্নলিখিত পরিচয়পত্রটি প্রদান করা হবে:
- অ্যাক্সেস টোকেন : একটি অ্যাক্সেস টোকেন ফেরত দেওয়া হয় যা অন্য একটি অ্যাক্সেস টোকেনের জন্য বিনিময় করা যেতে পারে। ফেসবুক দ্বারা সমর্থিত বিভিন্ন ধরণের অ্যাক্সেস টোকেন এবং কীভাবে আপনি সেগুলিকে দীর্ঘস্থায়ী টোকেনের জন্য বিনিময় করতে পারেন সে সম্পর্কে আরও জানুন।
গিটহাব
যখন কোনো ব্যবহারকারী GitHub দিয়ে সাইন ইন করবেন, তখন নিম্নলিখিত ক্রেডেনশিয়ালটি প্রদান করা হবে:
- অ্যাক্সেস টোকেন : বাতিল না করা পর্যন্ত এর মেয়াদ শেষ হয় না।
মাইক্রোসফট
যখন কোনো ব্যবহারকারী মাইক্রোসফ্ট দিয়ে সাইন ইন করবেন, তখন নিম্নলিখিত পরিচয়পত্রগুলি প্রদান করা হবে:
- আইডি টোকেন
- অ্যাক্সেস টোকেন
- রিফ্রেশ টোকেন : যদি
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 দিয়ে সাইন ইন করেন, তখন কোনো কাস্টম প্যারামিটার বা স্কোপ ছাড়াই নিম্নলিখিত ক্রেডেনশিয়ালগুলো পাস করা হবে:
- আইডি টোকেন
- অ্যাক্সেস টোকেন
- টোকেন রিফ্রেশ করুন
লিঙ্কডইন
যখন কোনো ব্যবহারকারী লিঙ্কডইন দিয়ে সাইন ইন করেন, তখন নিম্নলিখিত ক্রেডেনশিয়ালটি প্রদান করা হবে:
- অ্যাক্সেস টোকেন
আপেল
যখন কোনো ব্যবহারকারী Apple দিয়ে সাইন ইন করেন, তখন কোনো কাস্টম প্যারামিটার বা স্কোপ ছাড়াই নিম্নলিখিত ক্রেডেনশিয়ালগুলো পাস করা হবে:
- আইডি টোকেন
- অ্যাক্সেস টোকেন
- টোকেন রিফ্রেশ করুন
Common scenarios
নিম্নলিখিত উদাহরণগুলি ব্লকিং ফাংশনের কিছু সাধারণ ব্যবহার প্রদর্শন করে:
শুধুমাত্র একটি নির্দিষ্ট ডোমেইন থেকে নিবন্ধন করার অনুমতি দেওয়া হচ্ছে
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে example.com ডোমেনের অংশ নন এমন ব্যবহারকারীদের আপনার অ্যাপে নিবন্ধন করা থেকে বিরত রাখা যায়:
নোড.জেএস
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",
)
যাচাইবিহীন ইমেল ব্যবহারকারীদের নিবন্ধন করতে বাধা দেওয়া হচ্ছে
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে যাচাইবিহীন ইমেল ব্যবহারকারীদের আপনার অ্যাপে নিবন্ধন করা থেকে বিরত রাখা যায়:
নোড.জেএস
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.")
নির্দিষ্ট পরিচয় প্রদানকারীর ইমেলগুলিকে যাচাইকৃত হিসাবে গণ্য করা হচ্ছে
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে নির্দিষ্ট পরিচয় প্রদানকারী থেকে আসা ব্যবহারকারীর ইমেলগুলিকে যাচাইকৃত হিসাবে গণ্য করতে হয়:
নোড.জেএস
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)
নির্দিষ্ট কিছু আইপি ঠিকানা থেকে সাইন-ইন ব্লক করা হচ্ছে
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে নির্দিষ্ট আইপি অ্যাড্রেস রেঞ্জ থেকে সাইন-ইন ব্লক করা যায়:
নোড.জেএস
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.")
কাস্টম এবং সেশন দাবি সেট করা
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে কাস্টম এবং সেশন ক্লেইম সেট করতে হয়:
নোড.জেএস
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"]
})
সন্দেহজনক কার্যকলাপ নিরীক্ষণের জন্য আইপি ঠিকানা ট্র্যাক করা
ব্যবহারকারী যে আইপি অ্যাড্রেস থেকে সাইন ইন করেন, তা ট্র্যাক করে এবং পরবর্তী অনুরোধগুলোর আইপি অ্যাড্রেসের সাথে তুলনা করে আপনি টোকেন চুরি প্রতিরোধ করতে পারেন। যদি অনুরোধটি সন্দেহজনক মনে হয় — যেমন, আইপিগুলো ভিন্ন ভিন্ন ভৌগোলিক অঞ্চলের — তাহলে আপনি ব্যবহারকারীকে আবার সাইন ইন করতে বলতে পারেন।
ব্যবহারকারী যে আইপি অ্যাড্রেস দিয়ে সাইন ইন করেন তা ট্র্যাক করতে সেশন ক্লেইম ব্যবহার করুন:
নোড.জেএস
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})When a user attempts to access resources that require authentication with Firebase Authentication , compare the IP address in the request with the IP used to sign in:
নোড.জেএস
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)
ব্যবহারকারীর ছবি স্ক্রিনিং করা হচ্ছে
নিচের উদাহরণটি দেখায় কিভাবে ব্যবহারকারীদের প্রোফাইল ফটো পরিমার্জন করতে হয়:
নোড.জেএস
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 ক্রেডেনশিয়াল অ্যাক্সেস করা
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে গুগল দিয়ে সাইন ইন করা একজন ব্যবহারকারীর জন্য একটি রিফ্রেশ টোকেন সংগ্রহ করতে হয় এবং সেটি ব্যবহার করে গুগল ক্যালেন্ডার এপিআই কল করতে হয়। অফলাইন অ্যাক্সেসের জন্য রিফ্রেশ টোকেনটি সংরক্ষণ করা হয়।
নোড.জেএস
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 Authentication-এর সাথে reCAPTCHA Enterprise-কে একীভূত করার বিষয়ে আরও জানতে Enable reCAPTCHA Enterprise দেখুন।
কাস্টম ফ্যাক্টরের উপর ভিত্তি করে ফ্লো অনুমোদন বা ব্লক করতে ব্লকিং ফাংশন ব্যবহার করা যেতে পারে, যার ফলে reCAPTCHA Enterprise দ্বারা প্রদত্ত ফলাফল ওভাররাইড হয়ে যায়।
নোড.জেএস
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',
}
});