หากคุณได้อัปเกรดเป็น Firebase Authentication ด้วย Identity Platform คุณสามารถขยาย Firebase Authentication โดยใช้การปิดกั้น Cloud Functions
ฟังก์ชันการบล็อกช่วยให้คุณเรียกใช้โค้ดที่กำหนดเองซึ่งแก้ไขผลลัพธ์ของการลงทะเบียนผู้ใช้หรือลงชื่อเข้าใช้แอปของคุณ ตัวอย่างเช่น คุณสามารถป้องกันไม่ให้ผู้ใช้ตรวจสอบสิทธิ์หากพวกเขาไม่ตรงตามเกณฑ์ที่กำหนด หรืออัปเดตข้อมูลของผู้ใช้ก่อนที่จะส่งคืนไปยังแอปไคลเอนต์ของคุณ
ก่อนจะเริ่ม
หากต้องการใช้ฟังก์ชันการบล็อก คุณต้องอัปเกรดโปรเจ็กต์ Firebase เป็น Firebase Authentication ด้วย Identity Platform หากคุณยังไม่ได้อัปเกรด ให้ทำก่อน
ทำความเข้าใจกับฟังก์ชันการบล็อก
คุณสามารถลงทะเบียนฟังก์ชันการบล็อกสำหรับสองเหตุการณ์:
beforeCreate
: ทริกเกอร์ก่อนที่ผู้ใช้ใหม่จะถูกบันทึกลงในฐานข้อมูล Firebase Authentication และก่อนที่จะส่งโทเค็นกลับไปยังแอปไคลเอ็นต์ของคุณbeforeSignIn
: ทริกเกอร์หลังจากตรวจสอบข้อมูลรับรองของผู้ใช้แล้ว แต่ก่อนที่การตรวจสอบสิทธิ์ Firebase จะส่งคืนโทเค็น ID ไปยังแอปไคลเอ็นต์ของคุณ หากแอปของคุณใช้การตรวจสอบสิทธิ์แบบหลายปัจจัย ฟังก์ชันจะทริกเกอร์หลังจากที่ผู้ใช้ตรวจสอบปัจจัยที่สองแล้ว โปรดทราบว่าการสร้างผู้ใช้ใหม่จะทริกเกอร์beforeSignIn
ด้วยเช่นกัน นอกเหนือจากbeforeCreate
โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อใช้ฟังก์ชันการบล็อก:
ฟังก์ชันของคุณต้องตอบสนองภายใน 7 วินาที หลังจาก 7 วินาที การตรวจสอบสิทธิ์ Firebase จะส่งกลับข้อผิดพลาด และการดำเนินการของไคลเอ็นต์ล้มเหลว
รหัสตอบกลับ HTTP อื่นที่ไม่ใช่
200
จะถูกส่งไปยังแอปไคลเอนต์ของคุณ ตรวจสอบให้แน่ใจว่ารหัสลูกค้าของคุณจัดการกับข้อผิดพลาดที่ฟังก์ชันของคุณสามารถส่งคืนได้ฟังก์ชันต่างๆ มีผลกับผู้ใช้ทุกคนในโปรเจ็กต์ของคุณ รวมถึงฟังก์ชันใดๆ ที่มีอยู่ใน ผู้เช่า การตรวจสอบสิทธิ์ Firebase ให้ข้อมูลเกี่ยวกับผู้ใช้ในฟังก์ชันของคุณ รวมถึงผู้เช่าที่พวกเขาเป็นสมาชิก ดังนั้นคุณจึงสามารถตอบกลับได้
การเชื่อมโยงผู้ให้บริการข้อมูลประจำตัวรายอื่นกับบัญชีจะทริกเกอร์ฟังก์ชัน
beforeSignIn
ลงทะเบียนไว้อีกครั้งการรับรองความถูกต้องแบบไม่ระบุชื่อและแบบกำหนดเองจะไม่ทริกเกอร์ฟังก์ชันการบล็อก
ปรับใช้และลงทะเบียนฟังก์ชั่นการบล็อก
ในการแทรกโค้ดที่กำหนดเองของคุณลงในโฟลว์การตรวจสอบผู้ใช้ ให้ปรับใช้และลงทะเบียนฟังก์ชันการบล็อก เมื่อฟังก์ชันการบล็อกของคุณได้รับการปรับใช้และลงทะเบียนแล้ว โค้ดที่กำหนดเองของคุณต้องดำเนินการให้เสร็จสิ้นเพื่อให้การรับรองความถูกต้องและการสร้างผู้ใช้ทำได้สำเร็จ
ปรับใช้ฟังก์ชันการบล็อก
คุณปรับใช้ฟังก์ชันการบล็อกในลักษณะเดียวกับที่คุณปรับใช้ฟังก์ชันใดๆ (ดูรายละเอียดในหน้า เริ่มต้นใช้ งาน 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
เลือกแท็บ ฟังก์ชันการบล็อก
ลงทะเบียนฟังก์ชันการบล็อกของคุณโดยเลือกจากเมนูดรอปดาวน์ภายใต้ ก่อนการสร้างบัญชี (beforeCreate) หรือ Before sign in (beforeSignIn)
บันทึกการเปลี่ยนแปลงของคุณ
รับข้อมูลผู้ใช้และบริบท
เหตุการณ์ 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 หรือผู้เช่า | 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 | ข้อขัดแย้งของการทำงานพร้อมกัน เช่น ความขัดแย้งในการอ่าน-แก้ไข-เขียน |
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
ในตัวจัดการเหตุการณ์ทั้งสอง ค่าที่ตั้งไว้ใน beforeSignIn
จะเขียนทับค่าที่ตั้งไว้ใน beforeCreate
สำหรับ sessionClaims
เท่านั้น สิ่งเหล่านี้จะเผยแพร่ไปยังการอ้างสิทธิ์โทเค็นของเซสชันปัจจุบัน แต่จะไม่คงอยู่หรือเก็บไว้ในฐานข้อมูล
ตัวอย่างเช่น หากมีการตั้งค่า sessionClaims
beforeSignIn
จะส่งคืนด้วยการอ้างสิทธิ์ beforeCreate
และจะถูกรวมเข้าด้วยกัน เมื่อรวมกันแล้ว หากคีย์ sessionClaims
ตรงกับคีย์ใน customClaims
การอ้างสิทธิ์ customClaims
ที่ตรงกันจะถูกเขียนทับในการอ้างสิทธิ์โทเค็นโดยคีย์ sessionClaims
อย่างไรก็ตาม คีย์ customClaims
ที่ overwitten จะยังคงอยู่ในฐานข้อมูลสำหรับการร้องขอในอนาคต
ข้อมูลรับรองและข้อมูล OAuth ที่รองรับ
คุณสามารถส่งข้อมูลรับรองและข้อมูล OAuth ไปยังฟังก์ชันการบล็อกจากผู้ให้บริการข้อมูลประจำตัวต่างๆ ตารางต่อไปนี้แสดงข้อมูลประจำตัวและข้อมูลที่ได้รับการสนับสนุนสำหรับผู้ให้บริการข้อมูลประจำตัวแต่ละราย:
ผู้ให้บริการข้อมูลประจำตัว | โทเค็น ID | โทเค็นการเข้าถึง | เวลาหมดอายุ | ความลับของโทเค็น | รีเฟรชโทเค็น | การอ้างสิทธิ์ในการลงชื่อเข้าใช้ |
---|---|---|---|---|---|---|
ใช่ | ใช่ | ใช่ | ไม่ | ใช่ | ไม่ | |
ไม่ | ใช่ | ใช่ | ไม่ | ไม่ | ไม่ | |
ทวิตเตอร์ | ไม่ | ใช่ | ไม่ | ใช่ | ไม่ | ไม่ |
GitHub | ไม่ | ใช่ | ไม่ | ไม่ | ไม่ | ไม่ |
Microsoft | ใช่ | ใช่ | ใช่ | ไม่ | ใช่ | ไม่ |
ไม่ | ใช่ | ใช่ | ไม่ | ไม่ | ไม่ | |
Yahoo | ใช่ | ใช่ | ใช่ | ไม่ | ใช่ | ไม่ |
แอปเปิล | ใช่ | ใช่ | ใช่ | ไม่ | ใช่ | ไม่ |
SAML | ไม่ | ไม่ | ไม่ | ไม่ | ไม่ | ใช่ |
OIDC | ใช่ | ใช่ | ใช่ | ไม่ | ใช่ | ใช่ |
รีเฟรชโทเค็น
หากต้องการใช้โทเค็นการรีเฟรชในฟังก์ชันการบล็อก คุณต้องเลือกช่องทำเครื่องหมายในหน้า ฟังก์ชันการบล็อก ของคอนโซล 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
เมื่อผู้ใช้ลงชื่อเข้าใช้ Microsoft ข้อมูลประจำตัวต่อไปนี้จะถูกส่งต่อ:
- โทเค็น ID
- โทเค็นการเข้าถึง
- โทเค็นการรีเฟรช : ส่งผ่านไปยังฟังก์ชันการบล็อกหากเลือก ขอบเขต
offline_access
ตัวอย่าง:
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
Yahoo
เมื่อผู้ใช้ลงชื่อเข้าใช้ Yahoo ข้อมูลประจำตัวต่อไปนี้จะถูกส่งต่อไปโดยไม่มีพารามิเตอร์หรือขอบเขตที่กำหนดเอง:
- โทเค็น ID
- โทเค็นการเข้าถึง
- รีเฟรชโทเค็น
เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย LinkedIn ข้อมูลประจำตัวต่อไปนี้จะถูกส่งต่อ:
- โทเค็นการเข้าถึง
แอปเปิล
เมื่อผู้ใช้ลงชื่อเข้าใช้ Apple ข้อมูลประจำตัวต่อไปนี้จะถูกส่งต่อไปโดยไม่มีพารามิเตอร์หรือขอบเขตที่กำหนดเอง:
- โทเค็น ID
- โทเค็นการเข้าถึง
- รีเฟรชโทเค็น
สถานการณ์ทั่วไป
ตัวอย่างต่อไปนี้แสดงให้เห็นถึงกรณีการใช้งานทั่วไปสำหรับฟังก์ชันการบล็อก:
อนุญาตให้ลงทะเบียนจากโดเมนที่กำหนดเท่านั้น
ตัวอย่างต่อไปนี้แสดงวิธีป้องกันไม่ให้ผู้ใช้ที่ไม่ได้เป็นส่วนหนึ่งของโดเมน 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();
});
});
})
}
});