ฟังก์ชันการบล็อกให้คุณใช้โค้ดที่กำหนดเองซึ่งจะแก้ไขผลลัพธ์จากการที่ผู้ใช้ลงทะเบียนหรือลงชื่อเข้าใช้แอปของคุณ เช่น คุณสามารถป้องกันไม่ให้ผู้ใช้ตรวจสอบสิทธิ์หากไม่เป็นไปตามเกณฑ์ที่กำหนด หรืออัปเดตข้อมูลของผู้ใช้ก่อนที่จะส่งกลับไปยังแอปไคลเอ็นต์
ก่อนเริ่มต้น
หากต้องการใช้ฟังก์ชันการบล็อก คุณต้องอัปเกรดโปรเจ็กต์ Firebase เป็น Firebase Authentication with Identity Platform หากยังไม่ได้อัปเกรด ให้อัปเกรดก่อน
ทําความเข้าใจฟังก์ชันการบล็อก
คุณสามารถลงทะเบียนฟังก์ชันการบล็อกสําหรับเหตุการณ์ต่อไปนี้
beforeCreate
: ทริกเกอร์ก่อนบันทึกผู้ใช้ใหม่ไปยังฐานข้อมูล Firebase Authentication และก่อนส่งคืนโทเค็นไปยังแอปไคลเอ็นต์beforeSignIn
: ทริกเกอร์หลังจากยืนยันข้อมูลเข้าสู่ระบบของผู้ใช้แล้ว แต่ก่อนFirebase Authenticationจะแสดงผลโทเค็นระบุตัวตนไปยังแอปไคลเอ็นต์ หากแอปของคุณใช้การตรวจสอบสิทธิ์แบบหลายปัจจัย ฟังก์ชันนี้จะทริกเกอร์หลังจากที่ผู้ใช้ยืนยันปัจจัยที่ 2 โปรดทราบว่าการสร้างผู้ใช้ใหม่จะทริกเกอร์beforeSignIn
ด้วย นอกเหนือจากbeforeCreate
beforeEmail
(Node.js เท่านั้น): ทริกเกอร์ก่อนส่งอีเมล (เช่น
อีเมลลงชื่อเข้าใช้หรืออีเมลรีเซ็ตรหัสผ่าน) ไปยังผู้ใช้beforeSms
(Node.js เท่านั้น): ทริกเกอร์ก่อนส่งข้อความ SMS ไปยังผู้ใช้สำหรับกรณีต่างๆ เช่น การตรวจสอบสิทธิ์แบบหลายปัจจัย
โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อใช้ฟังก์ชันการบล็อก
ฟังก์ชันต้องตอบกลับภายใน 7 วินาที หลังจากผ่านไป 7 วินาที Firebase Authentication จะแสดงข้อผิดพลาด และการดำเนินการของไคลเอ็นต์จะล้มเหลว
ระบบจะส่งโค้ดการตอบกลับ HTTP ที่ไม่ใช่
200
ไปยังแอปไคลเอ็นต์ ตรวจสอบว่าโค้ดไคลเอ็นต์จัดการข้อผิดพลาดที่ฟังก์ชันอาจแสดงผลได้ฟังก์ชันจะมีผลกับผู้ใช้ทุกคนในโปรเจ็กต์ รวมถึงผู้ใช้ที่อยู่ในกลุ่มผู้ใช้ Firebase Authentication จะให้ข้อมูลเกี่ยวกับผู้ใช้สำหรับหน้าที่ของคุณ รวมถึงกลุ่มผู้ใช้ที่ตนอยู่ เพื่อให้คุณตอบกลับได้อย่างสอดคล้องกัน
การลิงก์ผู้ให้บริการข้อมูลประจำตัวรายอื่นกับบัญชีจะทริกเกอร์ฟังก์ชัน
beforeSignIn
ที่ลงทะเบียนไว้อีกครั้งการตรวจสอบสิทธิ์แบบไม่ระบุตัวตนและแบบกำหนดเองจะไม่ทริกเกอร์ฟังก์ชันการบล็อก
ทำให้ฟังก์ชันการบล็อกใช้งานได้
หากต้องการแทรกโค้ดที่กําหนดเองลงในขั้นตอนการตรวจสอบสิทธิ์ผู้ใช้ ให้ติดตั้งใช้งานฟังก์ชันการบล็อก เมื่อติดตั้งใช้งานฟังก์ชันการบล็อกแล้ว โค้ดที่กำหนดเองต้องทำงานเสร็จสมบูรณ์เพื่อให้การตรวจสอบสิทธิ์และการสร้างผู้ใช้สําเร็จ
คุณทำให้ฟังก์ชันการบล็อกใช้งานได้ในลักษณะเดียวกับที่ใช้งานฟังก์ชันอื่นๆ (ดูรายละเอียดในCloud Functionsหน้าเริ่มต้นใช้งาน) บทสรุปมีดังนี้:
เขียนฟังก์ชันที่จัดการเหตุการณ์เป้าหมาย
เช่น คุณอาจเพิ่มฟังก์ชันที่ไม่มีการดำเนินการต่อไปนี้ลงใน
index.js
เพื่อเริ่มต้นใช้งานconst functions = require('firebase-functions/v1'); exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => { // TODO }); The above example has omitted the implementation of custom auth logic. See the following sections to learn how to implement your blocking functions and [Common scenarios](#common-scenarios) for specific examples.
ทำให้ฟังก์ชันใช้งานได้โดยใช้ CLI ของ Firebase:
firebase deploy --only functions
คุณต้องทำให้ฟังก์ชันใช้งานได้อีกครั้งทุกครั้งที่อัปเดต
การดึงข้อมูลผู้ใช้และบริบท
เหตุการณ์ beforeSignIn
และ beforeCreate
มีออบเจ็กต์ User
และ EventContext
ที่มีข้อมูลเกี่ยวกับการลงชื่อเข้าใช้ของผู้ใช้ ใช้ค่าเหล่านี้ในโค้ดเพื่อพิจารณาว่าจะอนุญาตให้ดำเนินการต่อหรือไม่
ดูรายการพร็อพเพอร์ตี้ที่มีอยู่ในออบเจ็กต์ User
ได้ที่ข้อมูลอ้างอิง API ของ UserRecord
ออบเจ็กต์ EventContext
มีพร็อพเพอร์ตี้ต่อไปนี้
ชื่อ | คำอธิบาย | ตัวอย่าง |
---|---|---|
locale |
ภาษาของแอปพลิเคชัน คุณตั้งค่าภาษาได้โดยใช้ SDK ของไคลเอ็นต์ หรือส่งส่วนหัวภาษาใน REST API | fr หรือ sv-SE |
ipAddress
| ที่อยู่ IP ของอุปกรณ์ที่ผู้ใช้ปลายทางลงทะเบียนหรือลงชื่อเข้าใช้ | 114.14.200.1 |
userAgent
| User Agent ที่ทริกเกอร์ฟังก์ชันการบล็อก | 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
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 |
ความขัดแย้งในการดำเนินการพร้อมกัน เช่น ความขัดแย้งแบบ read-modify-write |
already-exists |
409 |
ทรัพยากรที่ไคลเอ็นต์พยายามสร้างมีอยู่แล้ว |
resource-exhausted |
429 |
โควต้าทรัพยากรหมดหรือถึงขีดการจำกัดอัตราคำขอ |
cancelled |
499 |
ไคลเอ็นต์ยกเลิกคำขอ |
data-loss |
500 |
ข้อมูลสูญหายโดยกู้คืนไม่ได้หรือข้อมูลเสียหาย |
unknown |
500 |
ข้อผิดพลาดของเซิร์ฟเวอร์ที่ไม่รู้จัก |
internal |
500 |
ข้อผิดพลาดภายในเซิร์ฟเวอร์ |
not-implemented |
501 |
เซิร์ฟเวอร์ไม่ได้นำเมธอด API มาใช้ |
unavailable |
503 |
ไม่พร้อมให้บริการ |
deadline-exceeded |
504 |
เกินกำหนดเวลาในการส่งคำขอแล้ว |
นอกจากนี้ คุณยังระบุข้อความแสดงข้อผิดพลาดที่กำหนดเองได้ด้วย โดยทำดังนี้
Node.js
throw new functions.auth.HttpsError('permission-denied', 'Unauthorized request origin!');
ตัวอย่างต่อไปนี้แสดงวิธีบล็อกไม่ให้ผู้ใช้ที่ไม่ได้อยู่ในโดเมนที่เจาะจงลงทะเบียนใช้แอป
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
// (If the user is authenticating within a tenant context, the tenant ID can be determined from
// user.tenantId or from context.resource, e.g. 'projects/project-id/tenant/tenant-id-1')
// Only users of a specific domain can sign up.
if (user.email.indexOf('@acme.com') === -1) {
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email "${user.email}"`);
}
});
ไม่ว่าคุณจะใช้ข้อความเริ่มต้นหรือข้อความที่กําหนดเอง Cloud Functions จะรวมข้อผิดพลาดและส่งกลับไปยังไคลเอ็นต์เป็นข้อผิดพลาดภายใน เช่น
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email user@evil.com}`);
แอปของคุณควรตรวจจับข้อผิดพลาดและจัดการกับข้อผิดพลาดดังกล่าว เช่น
JavaScript
// Blocking functions can also be triggered in a multi-tenant context before user creation.
// firebase.auth().tenantId = 'tenant-id-1';
firebase.auth().createUserWithEmailAndPassword('johndoe@example.com', 'password')
.then((result) => {
result.user.getIdTokenResult()
})
.then((idTokenResult) => {
console.log(idTokenResult.claim.admin);
})
.catch((error) => {
if (error.code !== 'auth/internal-error' && error.message.indexOf('Cloud Function') !== -1) {
// Display error.
} else {
// Registration succeeds.
}
});
การแก้ไขผู้ใช้
แทนที่จะบล็อกการลงทะเบียนหรือการพยายามลงชื่อเข้าใช้ คุณสามารถอนุญาตให้ดำเนินการต่อได้ แต่ให้แก้ไขออบเจ็กต์ User
ที่บันทึกไว้ในฐานข้อมูลของ Firebase Authentication แล้วส่งกลับไปยังไคลเอ็นต์
หากต้องการแก้ไขผู้ใช้ ให้แสดงผลออบเจ็กต์จากตัวแฮนเดิลเหตุการณ์ซึ่งมีช่องที่จะแก้ไข คุณสามารถแก้ไขช่องต่อไปนี้ได้
displayName
disabled
emailVerified
photoUrl
customClaims
sessionClaims
(beforeSignIn
เท่านั้น)
ยกเว้น sessionClaims
ระบบจะบันทึกฟิลด์ที่แก้ไขทั้งหมดลงในฐานข้อมูลของ Firebase Authentication ซึ่งหมายความว่าฟิลด์ดังกล่าวจะรวมอยู่ในโทเค็นการตอบกลับและคงอยู่ระหว่างเซสชันของผู้ใช้
ตัวอย่างต่อไปนี้แสดงวิธีตั้งชื่อที่แสดงเริ่มต้น
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
return {
// If no display name is provided, set it to "Guest".
displayName: user.displayName || 'Guest';
};
});
หากคุณลงทะเบียนเครื่องจัดการเหตุการณ์สําหรับทั้ง beforeCreate
และ beforeSignIn
โปรดทราบว่า beforeSignIn
จะทํางานหลังจาก beforeCreate
ช่องผู้ใช้ที่อัปเดตใน beforeCreate
จะปรากฏใน beforeSignIn
หากคุณตั้งค่าช่องอื่นที่ไม่ใช่ sessionClaims
ในตัวแฮนเดิลเหตุการณ์ทั้ง 2 รายการ ค่าที่กําหนดใน beforeSignIn
จะเขียนทับค่าที่กําหนดใน beforeCreate
สำหรับ sessionClaims
เท่านั้น ระบบจะนำไปเผยแพร่ไปยังการอ้างสิทธิ์โทเค็นของเซสชันปัจจุบัน แต่ไม่เก็บไว้หรือจัดเก็บในฐานข้อมูล
ตัวอย่างเช่น หากมีการตั้งค่า sessionClaims
beforeSignIn
จะแสดง sessionClaims
เหล่านั้นพร้อมกับการอ้างสิทธิ์ beforeCreate
และระบบจะผสานการอ้างสิทธิ์ เมื่อผสานรวมกัน หากคีย์ sessionClaims
ตรงกับคีย์ใน customClaims
ระบบจะเขียนทับ customClaims
ที่ตรงกันในการอ้างสิทธิ์โทเค็นด้วยคีย์ sessionClaims
อย่างไรก็ตาม คีย์ customClaims
ที่เขียนทับจะยังคงอยู่ในฐานข้อมูลสําหรับคําขอในอนาคต
ข้อมูลเข้าสู่ระบบและข้อมูลที่รองรับของ OAuth
คุณสามารถส่งข้อมูลเข้าสู่ระบบ OAuth และข้อมูลไปยังฟังก์ชันการบล็อกจากผู้ให้บริการข้อมูลประจำตัวต่างๆ ได้ ตารางต่อไปนี้แสดงข้อมูลเข้าสู่ระบบและข้อมูลที่รองรับสำหรับผู้ให้บริการข้อมูลประจำตัวแต่ละราย
ผู้ให้บริการข้อมูลประจำตัว | โทเค็นรหัส | โทเค็นเพื่อการเข้าถึง | เวลาหมดอายุ | ข้อมูลลับของโทเค็น | โทเค็นการรีเฟรช | การอ้างสิทธิ์ในการลงชื่อเข้าใช้ |
---|---|---|---|---|---|---|
ใช่ | ใช่ | ใช่ | ไม่ใช่ | ใช่ | ไม่ | |
ไม่ | ใช่ | ใช่ | ไม่ได้ | ไม่ใช่ | ไม่ | |
ไม่ | ใช่ | ไม่ใช่ | ใช่ | ไม่ได้ | ไม่ | |
GitHub | ไม่ | ใช่ | ไม่ได้ | ไม่ใช่ | ไม่ใช่ | ไม่ |
Microsoft | ใช่ | ใช่ | ใช่ | ไม่ใช่ | ใช่ | ไม่ |
ไม่ | ใช่ | ใช่ | ไม่ได้ | ไม่ใช่ | ไม่ | |
Yahoo | ใช่ | ใช่ | ใช่ | ไม่ใช่ | ใช่ | ไม่ |
Apple | ใช่ | ใช่ | ใช่ | ไม่ใช่ | ใช่ | ไม่ |
SAML | ไม่ | ไม่ใช่ | ไม่ใช่ | ไม่ใช่ | ไม่ได้ | ใช่ |
OIDC | ใช่ | ใช่ | ใช่ | ไม่ใช่ | ใช่ | ใช่ |
รีเฟรชโทเค็น
หากต้องการใช้โทเค็นรีเฟรชในฟังก์ชันการบล็อก คุณต้องเลือกช่องทําเครื่องหมายในหน้าฟังก์ชันการบล็อกของคอนโซล 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
หากผู้ใช้ให้ความยินยอมก่อนหน้านี้และไม่มีการขอขอบเขตใหม่
ตัวอย่าง
const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
'access_type': 'offline',
'prompt': 'consent'
});
firebase.auth().signInWithPopup(provider);
ดูข้อมูลเพิ่มเติมเกี่ยวกับโทเค็นการรีเฟรชของ Google
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Facebook ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้
- โทเค็นเพื่อการเข้าถึง: ระบบจะแสดงผลโทเค็นเพื่อการเข้าถึงที่แลกเปลี่ยนเป็นโทเค็นเพื่อการเข้าถึงอื่นได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับโทเค็นการเข้าถึงประเภทต่างๆ ที่ Facebook รองรับ และวิธีแลกเปลี่ยนโทเค็นเหล่านั้นเป็นโทเค็นที่มีอายุการใช้งานยาวนาน
GitHub
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย GitHub ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้
- โทเค็นการเข้าถึง: ไม่หมดอายุ เว้นแต่จะเพิกถอน
Microsoft
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Microsoft ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้
- โทเค็นรหัส
- โทเค็นการเข้าถึง
- โทเค็นรีเฟรช: ส่งไปยังฟังก์ชันการบล็อกหากเลือกขอบเขต
offline_access
ตัวอย่าง
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
Yahoo
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Yahoo ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้โดยไม่มีพารามิเตอร์หรือขอบเขตที่กำหนดเอง
- โทเค็นรหัส
- โทเค็นการเข้าถึง
- โทเค็นการรีเฟรช
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย LinkedIn ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้
- โทเค็นการเข้าถึง
Apple
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Apple ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้โดยไม่มีพารามิเตอร์หรือขอบเขตที่กำหนดเอง
- โทเค็นรหัส
- โทเค็นการเข้าถึง
- โทเค็นการรีเฟรช
สถานการณ์ที่พบบ่อย
ตัวอย่างต่อไปนี้แสดง Use Case ที่พบบ่อยสำหรับฟังก์ชันการบล็อก
อนุญาตให้จดทะเบียนจากโดเมนที่เฉพาะเจาะจงเท่านั้น
ตัวอย่างต่อไปนี้แสดงวิธีป้องกันไม่ให้ผู้ใช้ที่ไม่ได้อยู่ในโดเมน example.com
ลงทะเบียนกับแอปของคุณ
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (!user.email || user.email.indexOf('@example.com') === -1) {
throw new functions.auth.HttpsError(
'invalid-argument', `Unauthorized email "${user.email}"`);
}
});
การบล็อกไม่ให้ผู้ใช้ที่มีอีเมลที่ยังไม่ยืนยันลงทะเบียน
ตัวอย่างต่อไปนี้แสดงวิธีป้องกันไม่ให้ผู้ใช้ที่มีอีเมลที่ยังไม่ได้รับการยืนยันลงทะเบียนกับแอป
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.email && !user.emailVerified) {
throw new functions.auth.HttpsError(
'invalid-argument', `Unverified email "${user.email}"`);
}
});
กำหนดให้มีการยืนยันอีเมลเมื่อลงทะเบียน
ตัวอย่างต่อไปนี้แสดงวิธีกำหนดให้ผู้ใช้ยืนยันอีเมลหลังจากลงทะเบียน
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
const locale = context.locale;
if (user.email && !user.emailVerified) {
// Send custom email verification on sign-up.
return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
return sendCustomVerificationEmail(user.email, link, locale);
});
}
});
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (user.email && !user.emailVerified) {
throw new functions.auth.HttpsError(
'invalid-argument', `"${user.email}" needs to be verified before access is granted.`);
}
});
การจัดการกับอีเมลของผู้ให้บริการข้อมูลประจำตัวบางรายว่ายืนยันแล้ว
ตัวอย่างต่อไปนี้แสดงวิธีถือว่าอีเมลของผู้ใช้จากผู้ให้บริการข้อมูลประจำตัวบางรายได้รับการยืนยันแล้ว
Node.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 บางช่วง
Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (isSuspiciousIpAddress(context.ipAddress)) {
throw new functions.auth.HttpsError(
'permission-denied', 'Unauthorized access!');
}
});
การตั้งค่าการอ้างสิทธิ์ที่กำหนดเองและการอ้างสิทธิ์เซสชัน
ตัวอย่างต่อไปนี้แสดงวิธีตั้งค่าการอ้างสิทธิ์ที่กำหนดเองและการอ้างสิทธิ์เซสชัน
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (context.credential &&
context.credential.providerId === 'saml.my-provider-id') {
return {
// Employee ID does not change so save in persistent claims (stored in
// Auth DB).
customClaims: {
eid: context.credential.claims.employeeid,
},
// Copy role and groups to token claims. These will not be persisted.
sessionClaims: {
role: context.credential.claims.role,
groups: context.credential.claims.groups,
}
}
}
});
การติดตามที่อยู่ IP เพื่อตรวจสอบกิจกรรมที่น่าสงสัย
คุณสามารถป้องกันการโจรกรรมโทเค็นได้โดยติดตามที่อยู่ IP ที่ผู้ใช้ลงชื่อเข้าใช้ และเปรียบเทียบกับที่อยู่ IP ในคำขอที่ตามมา หากคำขอดูน่าสงสัย เช่น IP มาจากภูมิภาคทางภูมิศาสตร์ที่แตกต่างกัน คุณสามารถขอให้ผู้ใช้ลงชื่อเข้าใช้อีกครั้งได้
ใช้การอ้างสิทธิ์เซสชันเพื่อติดตามที่อยู่ IP ที่ผู้ใช้ลงชื่อเข้าใช้ด้วย โดยทำดังนี้
Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { return { sessionClaims: { signInIpAddress: context.ipAddress, }, }; });
เมื่อผู้ใช้พยายามเข้าถึงทรัพยากรที่ต้องมีการตรวจสอบสิทธิ์ด้วย Firebase Authentication ให้เปรียบเทียบที่อยู่ IP ในคำขอกับ IP ที่ใช้ลงชื่อเข้าใช้ ดังนี้
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!' }) }); } }); });
คัดกรองรูปภาพของผู้ใช้
ตัวอย่างต่อไปนี้แสดงวิธีทำให้รูปโปรไฟล์ของผู้ใช้ปลอดภัย
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.photoURL) {
return isPhotoAppropriate(user.photoURL)
.then((status) => {
if (!status) {
// Sanitize inappropriate photos by replacing them with guest photos.
// Users could also be blocked from sign-up, disabled, etc.
return {
photoUrl: PLACEHOLDER_GUEST_PHOTO_URL,
};
}
});
});
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีตรวจหาและทำให้รูปภาพปลอดภัยได้ในเอกสารประกอบของ 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
);
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();
});
});
})
}
});
การลบล้างผลการตัดสินของ reCAPTCHA Enterprise สําหรับการดำเนินการของผู้ใช้
ตัวอย่างต่อไปนี้แสดงวิธีลบล้างผลการตัดสินของ reCAPTCHA Enterprise สำหรับขั้นตอนของผู้ใช้ที่รองรับ
โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับการผสานรวม reCAPTCHA Enterprise กับ Firebase Authentication ได้ที่เปิดใช้ reCAPTCHA Enterprise
คุณใช้ฟังก์ชันการบล็อกเพื่ออนุญาตหรือบล็อกโฟลว์โดยอิงตามปัจจัยที่กำหนดเองได้ ซึ่งจะลบล้างผลลัพธ์ที่ได้รับจาก reCAPTCHA Enterprise
Node.js
const functions = require("firebase-functions/v1");
exports.beforesmsv1 = functions.auth.user().beforeSms((context) => {
if (
context.smsType === "SIGN_IN_OR_SIGN_UP" &&
context.additionalUserInfo.phoneNumber.includes('+91')
) {
return {
recaptchaActionOverride: "ALLOW",
};
}
// Allow users to sign in with recaptcha score greater than 0.5
if (event.additionalUserInfo.recaptchaScore > 0.5) {
return {
recaptchaActionOverride: 'ALLOW',
};
}
// Block all others.
return {
recaptchaActionOverride: 'BLOCK',
}
});