ฟังก์ชันการบล็อกช่วยให้คุณเรียกใช้โค้ดที่กำหนดเองซึ่งแก้ไขผลลัพธ์ของผู้ใช้ที่ลงทะเบียนหรือลงชื่อเข้าใช้แอปของคุณ ตัวอย่างเช่น คุณสามารถป้องกันไม่ให้ผู้ใช้ตรวจสอบสิทธิ์หากไม่ตรงตามเกณฑ์ที่กำหนด หรืออัปเดตข้อมูลของผู้ใช้ก่อนที่จะส่งคืนไปยังแอปไคลเอ็นต์ของคุณ
ก่อนที่คุณจะเริ่มต้น
หากต้องการใช้ฟังก์ชันการบล็อก คุณต้องอัปเกรดโปรเจ็กต์ Firebase เป็น Firebase Authentication ด้วย Identity Platform หากคุณยังไม่ได้อัปเกรด ให้ดำเนินการก่อน
ทำความเข้าใจเกี่ยวกับฟังก์ชันการบล็อก
คุณสามารถลงทะเบียนฟังก์ชั่นการบล็อกสำหรับสองเหตุการณ์:
beforeCreate
: ทริกเกอร์ก่อนที่ผู้ใช้ใหม่จะถูกบันทึกไปยังฐานข้อมูล Firebase Authentication และก่อนที่โทเค็นจะถูกส่งกลับไปยังแอปไคลเอ็นต์ของคุณbeforeSignIn
: ทริกเกอร์หลังจากยืนยันข้อมูลประจำตัวของผู้ใช้แล้ว แต่ก่อนที่ Firebase Authentication จะส่งคืนโทเค็น ID ไปยังแอปไคลเอ็นต์ของคุณ หากแอปของคุณใช้การยืนยันตัวตนแบบหลายปัจจัย ฟังก์ชันจะทริกเกอร์หลังจากที่ผู้ใช้ยืนยันปัจจัยที่สองของตน โปรดทราบว่าการสร้างผู้ใช้ใหม่จะทริกเกอร์beforeSignIn
เพิ่มเติมจากbeforeCreate
โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อใช้ฟังก์ชันการบล็อก:
ฟังก์ชันของคุณต้องตอบสนองภายใน 7 วินาที หลังจากผ่านไป 7 วินาที Firebase Authentication จะส่งกลับข้อผิดพลาด และการทำงานของไคลเอ็นต์ล้มเหลว
รหัสตอบกลับ HTTP ที่ไม่ใช่
200
จะถูกส่งผ่านไปยังแอปไคลเอ็นต์ของคุณ ตรวจสอบให้แน่ใจว่ารหัสไคลเอนต์ของคุณจัดการกับข้อผิดพลาดที่ฟังก์ชันของคุณส่งคืนได้ฟังก์ชันใช้กับผู้ใช้ทั้งหมดในโครงการของคุณ รวมถึงฟังก์ชันที่มีอยู่ใน ผู้เช่า การตรวจสอบความถูกต้องของ Firebase ให้ข้อมูลเกี่ยวกับผู้ใช้ในฟังก์ชันของคุณ รวมถึงผู้เช่าใดๆ ที่พวกเขาเป็นเจ้าของ ดังนั้นคุณจึงสามารถตอบสนองได้
การเชื่อมโยงผู้ให้บริการข้อมูลประจำตัวรายอื่นกับบัญชีจะทริกเกอร์ฟังก์ชัน
beforeSignIn
ที่ลงทะเบียนไว้อีกครั้งการรับรองความถูกต้องแบบไม่ระบุชื่อและแบบกำหนดเองจะไม่ทริกเกอร์ฟังก์ชันการบล็อก
ปรับใช้และลงทะเบียนฟังก์ชันการบล็อก
หากต้องการแทรกรหัสที่กำหนดเองของคุณในขั้นตอนการพิสูจน์ตัวตนผู้ใช้ ให้ปรับใช้และลงทะเบียนฟังก์ชันการบล็อก เมื่อฟังก์ชันการบล็อกของคุณได้รับการปรับใช้และลงทะเบียนแล้ว รหัสที่กำหนดเองของคุณจะต้องเสร็จสมบูรณ์เพื่อให้การตรวจสอบสิทธิ์และการสร้างผู้ใช้สำเร็จ
ปรับใช้ฟังก์ชันการบล็อก
คุณปรับใช้ฟังก์ชันการบล็อกในลักษณะเดียวกับที่คุณปรับใช้ฟังก์ชันใดๆ (ดูรายละเอียดได้ที่หน้า เริ่มต้นใช้งาน Cloud Functions) สรุป:
เขียน Cloud Functions ที่จัดการเหตุการณ์
beforeCreate
, เหตุการณ์beforeSignIn
หรือทั้งสองอย่างตัวอย่างเช่น ในการเริ่มต้น คุณสามารถเพิ่มฟังก์ชัน no-op ต่อไปนี้ใน
index.js
:const functions = require('firebase-functions'); exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => { // TODO }); exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { // TODO });
ตัวอย่างข้างต้นได้ละเว้นการใช้ตรรกะการรับรองความถูกต้องที่กำหนดเอง ดูส่วนต่อไปนี้เพื่อเรียนรู้วิธีใช้ฟังก์ชันการบล็อกและ สถานการณ์ทั่วไป สำหรับตัวอย่างที่เฉพาะเจาะจง
ปรับใช้ฟังก์ชันของคุณโดยใช้ Firebase CLI:
firebase deploy --only functions
คุณต้องปรับใช้ฟังก์ชันของคุณใหม่ทุกครั้งที่คุณอัปเดต
ลงทะเบียนฟังก์ชั่นการปิดกั้น
ไปที่หน้า การตั้งค่า การตรวจสอบความถูกต้องของ Firebase ในคอนโซล Firebase
เลือกแท็บ ฟังก์ชั่นการปิดกั้น
ลงทะเบียนฟังก์ชันการบล็อกของคุณโดยเลือกจากเมนูแบบเลื่อนลงใต้ ก่อนสร้างบัญชี (ก่อนสร้าง) หรือ ก่อนลงชื่อเข้าใช้ (ก่อนลงชื่อเข้าใช้)
บันทึกการเปลี่ยนแปลงของคุณ
รับข้อมูลผู้ใช้และบริบท
เหตุการณ์ beforeSignIn
และ beforeCreate
มีวัตถุ User
และ EventContext
ที่มีข้อมูลเกี่ยวกับการลงชื่อเข้าใช้ของผู้ใช้ ใช้ค่าเหล่านี้ในโค้ดของคุณเพื่อพิจารณาว่าจะอนุญาตให้ดำเนินการต่อหรือไม่
สำหรับรายการของคุณสมบัติที่มีอยู่ในอ็อบเจกต์ User
โปรดดู การอ้างอิง UserRecord
API
วัตถุ EventContext
มีคุณสมบัติดังต่อไปนี้:
ชื่อ | คำอธิบาย | ตัวอย่าง |
---|---|---|
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
ในฟังก์ชันของคุณ ตัวอย่างเช่น:
โหนด js
throw new functions.auth.HttpsError('permission-denied');
ตารางต่อไปนี้แสดงรายการข้อผิดพลาดที่คุณสามารถแจ้งได้ พร้อมด้วยข้อความแสดงข้อผิดพลาดเริ่มต้น:
ชื่อ | รหัส | ข้อความ |
---|---|---|
invalid-argument | 400 | ลูกค้าระบุอาร์กิวเมนต์ที่ไม่ถูกต้อง |
failed-precondition | 400 | ไม่สามารถดำเนินการคำขอในสถานะระบบปัจจุบัน |
out-of-range | 400 | ลูกค้าระบุช่วงที่ไม่ถูกต้อง |
unauthenticated | 401 | โทเค็น OAuth ขาดหายไป ไม่ถูกต้อง หรือหมดอายุ |
permission-denied | 403 | ลูกค้าไม่ได้รับอนุญาตเพียงพอ |
not-found | 404 | ไม่พบทรัพยากรที่ระบุ |
aborted | 409 | ความขัดแย้งที่เกิดขึ้นพร้อมกัน เช่น ความขัดแย้งในการอ่าน-แก้ไข-เขียน |
already-exists | 409 | ทรัพยากรที่ไคลเอนต์พยายามสร้างมีอยู่แล้ว |
resource-exhausted | 429 | โควต้าทรัพยากรหมดหรือถึงขีดจำกัดอัตรา |
cancelled | 499 | คำขอถูกยกเลิกโดยลูกค้า |
data-loss | 500 | การสูญเสียข้อมูลที่กู้คืนไม่ได้หรือข้อมูลเสียหาย |
unknown | 500 | ข้อผิดพลาดของเซิร์ฟเวอร์ที่ไม่รู้จัก |
internal | 500 | ข้อผิดพลาดภายในเซิร์ฟเวอร์ |
not-implemented | 501 | เซิร์ฟเวอร์ไม่ได้ใช้วิธี API |
unavailable | 503 | ไม่สามารถให้บริการได้. |
deadline-exceeded | 504 | เกินกำหนดส่งคำขอแล้ว |
คุณยังสามารถระบุข้อความแสดงข้อผิดพลาดที่กำหนดเอง:
โหนด js
throw new functions.auth.HttpsError('permission-denied', 'Unauthorized request origin!');
ตัวอย่างต่อไปนี้แสดงวิธีบล็อกผู้ใช้ที่ไม่ได้อยู่ในโดเมนเฉพาะไม่ให้ลงทะเบียนแอปของคุณ:
โหนด 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}"`);
}
});
ไม่ว่าคุณจะใช้ข้อความเริ่มต้นหรือแบบกำหนดเอง Cloud Functions จะรวมข้อผิดพลาดและส่งกลับไปยังไคลเอ็นต์เป็นข้อผิดพลาดภายใน ตัวอย่างเช่น:
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email user@evil.com}`);
แอปของคุณควรตรวจจับข้อผิดพลาดและจัดการตามนั้น ตัวอย่างเช่น:
จาวาสคริปต์
// 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.
}
});
การปรับเปลี่ยนผู้ใช้
แทนที่จะปิดกั้นการลงทะเบียนหรือการพยายามลงชื่อเข้าใช้ คุณสามารถอนุญาตให้ดำเนินการต่อไปได้ แต่แก้ไขอ็อบเจ็กต์ User
ที่บันทึกไว้ในฐานข้อมูลของ Firebase Authentication และส่งคืนไปยังไคลเอนต์
หากต้องการแก้ไขผู้ใช้ ให้ส่งคืนออบเจกต์จากตัวจัดการเหตุการณ์ที่มีฟิลด์เพื่อแก้ไข คุณสามารถแก้ไขฟิลด์ต่อไปนี้:
-
displayName
-
disabled
-
emailVerified
-
photoURL
-
customClaims
-
sessionClaims
(beforeSignIn
เท่านั้น)
ยกเว้น sessionClaims
ที่แก้ไขทั้งหมดจะถูกบันทึกลงในฐานข้อมูลของ Firebase Authentication ซึ่งหมายความว่าจะรวมอยู่ในโทเค็นการตอบสนองและคงอยู่ระหว่างเซสชันของผู้ใช้
ตัวอย่างต่อไปนี้แสดงวิธีการตั้งชื่อที่แสดงเริ่มต้น:
โหนด js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
return {
// If no display name is provided, set it to "Guest".
displayName: user.displayName || 'Guest';
};
});
หากคุณลงทะเบียนตัวจัดการเหตุการณ์สำหรับทั้ง beforeCreate
และ beforeSignIn
โปรดทราบว่า beforeSignIn
ดำเนินการหลังจาก beforeCreate
ฟิลด์ผู้ใช้ที่อัปเดตใน beforeCreate
จะมองเห็นได้ใน beforeSignIn
หากคุณตั้งค่าฟิลด์อื่นที่ไม่ใช่ sessionClaims
ในตัวจัดการเหตุการณ์ทั้งสอง ค่าที่ตั้งค่าใน beforeSignIn
จะเขียนทับค่าที่ตั้งค่าใน beforeCreate
สำหรับ sessionClaims
เท่านั้น การอ้างสิทธิ์ดังกล่าวจะเผยแพร่ไปยังการอ้างสิทธิ์โทเค็นของเซสชันปัจจุบัน แต่จะไม่คงอยู่หรือจัดเก็บไว้ในฐานข้อมูล
ตัวอย่างเช่น หากมีการตั้ง sessionClaims
beforeSignIn
จะส่งคืนด้วยการอ้างสิทธิ์ beforeCreate
และจะมีการรวมเข้าด้วยกัน เมื่อรวมเข้าด้วยกัน หากคีย์ sessionClaims
ตรงกับคีย์ใน customClaims
customClaims
ที่กำหนดเองที่ตรงกันจะถูกเขียนทับในการอ้างสิทธิ์โทเค็นโดยคีย์ sessionClaims
อย่างไรก็ตาม คีย์ customClaims
ที่ถูกทับจะยังคงอยู่ในฐานข้อมูลสำหรับคำขอในอนาคต
ข้อมูลรับรอง OAuth และข้อมูลที่รองรับ
คุณสามารถส่งข้อมูลรับรอง OAuth และข้อมูลไปยังฟังก์ชันการบล็อกจากผู้ให้บริการข้อมูลประจำตัวต่างๆ ตารางต่อไปนี้แสดงข้อมูลประจำตัวและข้อมูลที่ได้รับการสนับสนุนสำหรับผู้ให้บริการข้อมูลประจำตัวแต่ละราย:
ผู้ให้บริการข้อมูลประจำตัว | โทเค็น ID | โทเค็นการเข้าถึง | เวลาหมดอายุ | ความลับของโทเค็น | รีเฟรชโทเค็น | การอ้างสิทธิ์ในการลงชื่อเข้าใช้ |
---|---|---|---|---|---|---|
ใช่ | ใช่ | ใช่ | เลขที่ | ใช่ | เลขที่ | |
เฟสบุ๊ค | เลขที่ | ใช่ | ใช่ | เลขที่ | เลขที่ | เลขที่ |
ทวิตเตอร์ | เลขที่ | ใช่ | เลขที่ | ใช่ | เลขที่ | เลขที่ |
GitHub | เลขที่ | ใช่ | เลขที่ | เลขที่ | เลขที่ | เลขที่ |
ไมโครซอฟท์ | ใช่ | ใช่ | ใช่ | เลขที่ | ใช่ | เลขที่ |
ลิงค์อิน | เลขที่ | ใช่ | ใช่ | เลขที่ | เลขที่ | เลขที่ |
ยาฮู | ใช่ | ใช่ | ใช่ | เลขที่ | ใช่ | เลขที่ |
แอปเปิล | ใช่ | ใช่ | ใช่ | เลขที่ | ใช่ | เลขที่ |
SAML | เลขที่ | เลขที่ | เลขที่ | เลขที่ | เลขที่ | ใช่ |
คปภ | ใช่ | ใช่ | ใช่ | เลขที่ | ใช่ | ใช่ |
รีเฟรชโทเค็น
หากต้องการใช้โทเค็นรีเฟรชในฟังก์ชันการบล็อก คุณต้องเลือกช่องทำเครื่องหมายในหน้า ฟังก์ชันการบล็อก ของคอนโซล Firebase ก่อน
ผู้ให้บริการข้อมูลประจำตัวจะไม่ส่งคืนโทเค็นการรีเฟรชเมื่อลงชื่อเข้าใช้โดยตรงด้วยข้อมูลรับรอง OAuth เช่น โทเค็น ID หรือโทเค็นการเข้าถึง ในสถานการณ์นี้ ข้อมูลรับรอง OAuth ฝั่งไคลเอ็นต์เดียวกันจะถูกส่งผ่านไปยังฟังก์ชันการบล็อก
ส่วนต่อไปนี้จะอธิบายประเภทผู้ให้บริการข้อมูลประจำตัวแต่ละประเภทและข้อมูลประจำตัวและข้อมูลที่รองรับ
ผู้ให้บริการ OIDC ทั่วไป
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วยผู้ให้บริการ OIDC ทั่วไป ข้อมูลประจำตัวต่อไปนี้จะถูกส่งผ่าน:
- โทเค็น ID : ระบุหากเลือกโฟลว์
id_token
- โทเค็นการเข้าถึง : มีให้หากเลือกโฟลว์โค้ด โปรดทราบว่าขณะนี้โค้ดโฟลว์รองรับผ่าน REST API เท่านั้น
- รีเฟรชโทเค็น : ระบุหากเลือก ขอบเขต
offline_access
ตัวอย่าง:
const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Google ข้อมูลรับรองต่อไปนี้จะถูกส่งผ่าน:
- โทเค็น ID
- โทเค็นการเข้าถึง
- โทเค็นการรีเฟรช : ให้เฉพาะเมื่อมีการร้องขอพารามิเตอร์ที่กำหนดเองต่อไปนี้:
-
access_type=offline
-
prompt=consent
หากผู้ใช้ให้ความยินยอมก่อนหน้านี้และไม่มีการร้องขอขอบเขตใหม่
-
ตัวอย่าง:
const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
'access_type': 'offline',
'prompt': 'consent'
});
firebase.auth().signInWithPopup(provider);
เรียนรู้เพิ่มเติมเกี่ยวกับ โทเค็นการรีเฟรชของ Google
เฟสบุ๊ค
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Facebook ข้อมูลประจำตัวต่อไปนี้จะถูกส่งผ่าน:
- โทเค็นการเข้าถึง : โทเค็นการเข้าถึงจะถูกส่งคืนซึ่งสามารถแลกเปลี่ยนเป็นโทเค็นการเข้าถึงอื่นได้ เรียนรู้เพิ่มเติมเกี่ยวกับประเภทต่างๆ ของ โทเค็นการเข้าถึง ที่สนับสนุนโดย Facebook และวิธีที่คุณสามารถแลกเปลี่ยนเป็น โทเค็นที่มีอายุยืน
GitHub
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย GitHub ข้อมูลรับรองต่อไปนี้จะถูกส่งผ่าน:
- โทเค็นการเข้าถึง : ไม่หมดอายุเว้นแต่จะถูกเพิกถอน
ไมโครซอฟท์
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Microsoft ข้อมูลรับรองต่อไปนี้จะถูกส่งผ่าน:
- โทเค็น ID
- โทเค็นการเข้าถึง
- รีเฟรชโทเค็น : ส่งผ่านไปยังฟังก์ชันการบล็อกหากเลือก ขอบเขต
offline_access
ตัวอย่าง:
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
ยาฮู
เมื่อผู้ใช้ลงชื่อเข้าใช้ Yahoo ข้อมูลประจำตัวต่อไปนี้จะถูกส่งผ่านโดยไม่มีพารามิเตอร์หรือขอบเขตที่กำหนดเอง:
- โทเค็น ID
- โทเค็นการเข้าถึง
- รีเฟรชโทเค็น
ลิงค์อิน
เมื่อผู้ใช้ลงชื่อเข้าใช้ LinkedIn ข้อมูลรับรองต่อไปนี้จะถูกส่งผ่าน:
- โทเค็นการเข้าถึง
แอปเปิล
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Apple ข้อมูลรับรองต่อไปนี้จะถูกส่งผ่านโดยไม่มีพารามิเตอร์หรือขอบเขตที่กำหนดเอง:
- โทเค็น ID
- โทเค็นการเข้าถึง
- รีเฟรชโทเค็น
สถานการณ์ทั่วไป
ตัวอย่างต่อไปนี้แสดงกรณีการใช้งานทั่วไปสำหรับฟังก์ชันการบล็อก:
อนุญาตให้ลงทะเบียนจากโดเมนที่ระบุเท่านั้น
ตัวอย่างต่อไปนี้แสดงวิธีป้องกันไม่ให้ผู้ใช้ที่ไม่ได้เป็นส่วนหนึ่งของโดเมน example.com
ลงทะเบียนกับแอปของคุณ:
โหนด 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}"`);
}
});
บล็อกผู้ใช้ที่มีอีเมลที่ไม่ได้รับการยืนยันไม่ให้ลงทะเบียน
ตัวอย่างต่อไปนี้แสดงวิธีป้องกันไม่ให้ผู้ใช้ที่มีอีเมลที่ไม่ได้รับการยืนยันลงทะเบียนกับแอปของคุณ:
โหนด 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}"`);
}
});
ต้องการการยืนยันอีเมลในการลงทะเบียน
ตัวอย่างต่อไปนี้แสดงวิธีกำหนดให้ผู้ใช้ยืนยันอีเมลหลังจากลงทะเบียน:
โหนด 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.`);
}
});
การปฏิบัติต่ออีเมลของผู้ให้บริการข้อมูลประจำตัวบางอย่างว่าได้รับการยืนยันแล้ว
ตัวอย่างต่อไปนี้แสดงวิธีจัดการกับอีเมลของผู้ใช้จากผู้ให้บริการข้อมูลประจำตัวบางรายว่าได้รับการยืนยันแล้ว:
โหนด js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.email && !user.emailVerified && context.eventType.indexOf(':facebook.com') !== -1) {
return {
emailVerified: true,
};
}
});
การบล็อกการลงชื่อเข้าใช้จากที่อยู่ IP บางอย่าง
ตัวอย่างต่อไปนี้บล็อกการลงชื่อเข้าใช้จากช่วงที่อยู่ IP บางช่วง:
โหนด js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (isSuspiciousIpAddress(context.ipAddress)) {
throw new functions.auth.HttpsError(
'permission-denied', 'Unauthorized access!');
}
});
การตั้งค่าแบบกำหนดเองและการอ้างสิทธิ์เซสชัน
ตัวอย่างต่อไปนี้แสดงวิธีการตั้งค่าแบบกำหนดเองและการอ้างสิทธิ์เซสชัน:
โหนด 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,
}
}
}
});
ติดตามที่อยู่ IP เพื่อตรวจสอบกิจกรรมที่น่าสงสัย
คุณสามารถป้องกันการขโมยโทเค็นได้โดยการติดตามที่อยู่ IP ที่ผู้ใช้ลงชื่อเข้าใช้ และเปรียบเทียบกับที่อยู่ IP ในคำขอที่ตามมา หากคำขอดูน่าสงสัย เช่น IP มาจากภูมิภาคทางภูมิศาสตร์ที่แตกต่างกัน คุณสามารถขอให้ผู้ใช้ลงชื่อเข้าใช้อีกครั้ง
ใช้การอ้างสิทธิ์เซสชันเพื่อติดตามที่อยู่ IP ที่ผู้ใช้ลงชื่อเข้าใช้:
โหนด js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { return { sessionClaims: { signInIpAddress: context.ipAddress, }, }; });
เมื่อผู้ใช้พยายามเข้าถึงทรัพยากรที่ต้องการการตรวจสอบสิทธิ์ด้วย Firebase Authentication ให้เปรียบเทียบที่อยู่ IP ในคำขอกับ IP ที่ใช้ในการลงชื่อเข้าใช้:
โหนด 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!' }) }); } }); });
คัดกรองภาพถ่ายของผู้ใช้
ตัวอย่างต่อไปนี้แสดงวิธีฆ่าเชื้อรูปโปรไฟล์ของผู้ใช้:
โหนด 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,
};
}
});
});
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีตรวจจับและฆ่าเชื้อภาพ โปรดดูเอกสารประกอบของ Cloud Vision
การเข้าถึงข้อมูลรับรอง OAuth ของผู้ให้บริการข้อมูลประจำตัวของผู้ใช้
ตัวอย่างต่อไปนี้สาธิตวิธีรับโทเค็นการรีเฟรชสำหรับผู้ใช้ที่ลงชื่อเข้าใช้ด้วย Google และใช้เพื่อเรียกใช้ Google Calendar API โทเค็นการรีเฟรชถูกเก็บไว้สำหรับการเข้าถึงแบบออฟไลน์
โหนด 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();
});
});
})
}
});