ทริกเกอร์การบล็อกการตรวจสอบสิทธิ์


ฟังก์ชันการบล็อกให้คุณใช้โค้ดที่กำหนดเองซึ่งจะแก้ไขผลลัพธ์จากการที่ผู้ใช้ลงทะเบียนหรือลงชื่อเข้าใช้แอปของคุณ ตัวอย่างเช่น คุณสามารถป้องกันไม่ให้ผู้ใช้ตรวจสอบสิทธิ์หากผู้ใช้ไม่เป็นไปตามเกณฑ์ที่กำหนด หรืออัปเดตข้อมูลของผู้ใช้ก่อนที่จะส่งกลับไปยังแอปไคลเอ็นต์

ก่อนเริ่มต้น

หากต้องการใช้ฟังก์ชันการบล็อก คุณต้องอัปเกรดโปรเจ็กต์ Firebase เป็น Firebase Authentication with Identity Platform หากยังไม่ได้อัปเกรด ให้ดำเนินการก่อน

ทำความเข้าใจฟังก์ชันการบล็อก

คุณลงทะเบียนฟังก์ชันการบล็อกสำหรับเหตุการณ์ต่อไปนี้ได้

  • beforeCreate: ทริกเกอร์ก่อนที่จะบันทึกผู้ใช้ใหม่ลงในฐานข้อมูล Firebase Authentication และก่อนที่จะส่งคืนโทเค็นไปยังแอปไคลเอ็นต์

  • beforeSignIn: ทริกเกอร์หลังจากที่ระบบยืนยันข้อมูลเข้าสู่ระบบของผู้ใช้ แต่ก่อนที่ Firebase Authentication จะส่งโทเค็นรหัสไปยังแอปไคลเอ็นต์ หากแอปใช้การตรวจสอบสิทธิ์แบบหลายปัจจัย ฟังก์ชันจะทริกเกอร์หลังจากที่ผู้ใช้ยืนยันปัจจัยที่ 2 โปรดทราบว่าการสร้างผู้ใช้ใหม่จะทริกเกอร์ beforeSignIn ด้วย นอกเหนือจาก beforeCreate

  • beforeEmail (Node.js เท่านั้น): ทริกเกอร์ก่อนที่จะส่งอีเมล (เช่น
    อีเมลลงชื่อเข้าใช้หรืออีเมลรีเซ็ตรหัสผ่าน) ไปยังผู้ใช้

  • beforeSms (Node.js เท่านั้น): ทริกเกอร์ก่อนที่จะส่งข้อความ SMS ไปยังผู้ใช้ ในกรณีต่างๆ เช่น การตรวจสอบสิทธิ์แบบ 2 ปัจจัย

โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อใช้ฟังก์ชันการบล็อก

  • ฟังก์ชันของคุณต้องตอบกลับภายใน 7 วินาที หลังจากผ่านไป 7 วินาที Firebase Authentication จะแสดงข้อผิดพลาดและการดำเนินการของไคลเอ็นต์จะล้มเหลว

  • ระบบจะส่งรหัสการตอบกลับ HTTP อื่นๆ นอกเหนือจาก 200 ไปยังแอปไคลเอ็นต์ ตรวจสอบว่าโค้ดไคลเอ็นต์จัดการข้อผิดพลาดที่ฟังก์ชันแสดงได้

  • ฟังก์ชันจะมีผลต่อผู้ใช้ทุกคนในโปรเจ็กต์ รวมถึงผู้ใช้ที่อยู่ในกลุ่มผู้ใช้ Firebase Authentication จะให้ข้อมูลเกี่ยวกับผู้ใช้แก่ฟังก์ชันของคุณ ซึ่งรวมถึง ผู้เช่าที่ผู้ใช้สังกัด เพื่อให้คุณตอบสนองได้อย่างเหมาะสม

  • การลิงก์ผู้ให้บริการข้อมูลประจำตัวรายอื่นกับบัญชีจะทริกเกอร์ฟังก์ชัน beforeSignInที่ลงทะเบียนไว้ซ้ำ

  • การตรวจสอบสิทธิ์แบบไม่ระบุตัวตนและแบบกำหนดเองจะไม่ทริกเกอร์ฟังก์ชันการบล็อก

ทําให้ฟังก์ชันการบล็อกใช้งานได้

หากต้องการแทรกโค้ดที่กำหนดเองลงในโฟลว์การตรวจสอบสิทธิ์ผู้ใช้ ให้ติดตั้งฟังก์ชันการบล็อก เมื่อติดตั้งใช้งานฟังก์ชันการบล็อกแล้ว โค้ดที่กำหนดเองต้องทำงานให้เสร็จสมบูรณ์เพื่อการตรวจสอบสิทธิ์และการสร้างผู้ใช้ให้สำเร็จ

คุณจะติดตั้งฟังก์ชันการบล็อกในลักษณะเดียวกับการติดตั้งฟังก์ชันอื่นๆ (ดูรายละเอียดในหน้าCloud Functions เริ่มต้นใช้งาน) บทสรุปมีดังนี้:

  1. เขียนฟังก์ชันที่จัดการเหตุการณ์เป้าหมาย

    เช่น หากต้องการเริ่มต้นใช้งาน คุณสามารถเพิ่มฟังก์ชันที่ไม่มีการดำเนินการ เช่น ฟังก์ชันต่อไปนี้ลงใน 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.
    
  1. ทำให้ฟังก์ชันใช้งานได้โดยใช้ FirebaseCLI:

    firebase deploy --only functions
    

    คุณต้องติดตั้งฟังก์ชันอีกครั้งทุกครั้งที่อัปเดต

การรับข้อมูลผู้ใช้และบริบท

เหตุการณ์ beforeSignIn และ beforeCreate จะให้ออบเจ็กต์ User และ EventContext ซึ่งมีข้อมูลเกี่ยวกับการลงชื่อเข้าใช้ของผู้ใช้ ใช้ค่าเหล่านี้ ในโค้ดเพื่อพิจารณาว่าจะอนุญาตให้ดำเนินการต่อหรือไม่

ดูรายการพร็อพเพอร์ตี้ที่ใช้ได้ในออบเจ็กต์ User ได้ที่เอกสารอ้างอิงUserRecord API

ออบเจ็กต์ EventContext มีพร็อพเพอร์ตี้ต่อไปนี้

ชื่อ คำอธิบาย ตัวอย่าง
locale ภาษาของแอปพลิเคชัน คุณตั้งค่าภาษาได้โดยใช้ Client 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 จะแสดงค่าเหล่านั้น พร้อมกับการอ้างสิทธิ์ beforeCreate และจะมีการผสานรวมค่าเหล่านั้น เมื่อผสานรวม หากsessionClaimsตรงกับคีย์ใน customClaims ระบบจะเขียนทับcustomClaimsที่ตรงกันในคำกล่าวอ้างของโทเค็นด้วยคีย์ sessionClaims อย่างไรก็ตาม ระบบจะยังคงเก็บคีย์ customClaims ที่เขียนทับไว้ใน ฐานข้อมูลสำหรับคำขอในอนาคต

ข้อมูลเข้าสู่ระบบและข้อมูล OAuth ที่รองรับ

คุณส่งข้อมูลเข้าสู่ระบบและข้อมูล OAuth ไปยังฟังก์ชันการบล็อกจากผู้ให้บริการข้อมูลประจำตัวต่างๆ ได้ ตารางต่อไปนี้แสดงข้อมูลเข้าสู่ระบบและข้อมูลที่ รองรับสำหรับผู้ให้บริการข้อมูลประจำตัวแต่ละราย

ผู้ให้บริการข้อมูลประจำตัว โทเค็นรหัส โทเค็นเพื่อการเข้าถึง เวลาหมดอายุ โทเค็นลับ โทเค็นการรีเฟรช การอ้างสิทธิ์ในการลงชื่อเข้าใช้
Google ใช่ ใช่ ใช่ ไม่ใช่ ใช่ ไม่
Facebook ไม่ ใช่ ใช่ ไม่ได้ ไม่ใช่ ไม่
Twitter ไม่ ใช่ ไม่ใช่ ใช่ ไม่ได้ ไม่
GitHub ไม่ ใช่ ไม่ได้ ไม่ใช่ ไม่ใช่ ไม่
Microsoft ใช่ ใช่ ใช่ ไม่ใช่ ใช่ ไม่
LinkedIn ไม่ ใช่ ใช่ ไม่ได้ ไม่ใช่ ไม่
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

เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย 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 ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้

  • โทเค็นเพื่อการเข้าถึง: ระบบจะแสดงโทเค็นเพื่อการเข้าถึงที่สามารถแลกเปลี่ยนเป็นโทเค็นเพื่อการเข้าถึงอื่นได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับโทเค็นเพื่อการเข้าถึงประเภทต่างๆ ที่ 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

เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย LinkedIn ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้

  • โทเค็นเพื่อการเข้าถึง

Apple

เมื่อผู้ใช้ลงชื่อเข้าใช้ด้วย Apple ระบบจะส่งข้อมูลเข้าสู่ระบบต่อไปนี้ โดยไม่มีพารามิเตอร์หรือขอบเขตที่กำหนดเอง

  • โทเค็นรหัส
  • โทเค็นเพื่อการเข้าถึง
  • โทเค็นการรีเฟรช

สถานการณ์ที่พบบ่อย

ตัวอย่างต่อไปนี้แสดงกรณีการใช้งานฟังก์ชันการบล็อกที่พบบ่อย

อนุญาตให้ลงทะเบียนจากโดเมนที่เฉพาะเจาะจงเท่านั้น

ตัวอย่างต่อไปนี้แสดงวิธีป้องกันไม่ให้ผู้ใช้ที่ไม่ได้อยู่ในโดเมน 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 มาจากภูมิภาคทางภูมิศาสตร์ที่แตกต่างกัน คุณสามารถขอให้ผู้ใช้ลงชื่อเข้าใช้อีกครั้งได้

  1. ใช้การอ้างสิทธิ์เซสชันเพื่อติดตามที่อยู่ IP ที่ผู้ใช้ลงชื่อเข้าใช้

    Node.js

    exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
      return {
        sessionClaims: {
          signInIpAddress: context.ipAddress,
        },
      };
    });
    
  2. เมื่อผู้ใช้พยายามเข้าถึงทรัพยากรที่ต้องมีการตรวจสอบสิทธิ์ด้วย 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',
 }
});