Xác thực bằng Firebase bằng số điện thoại bằng JavaScript

Bạn có thể sử dụng Firebase Authentication để đăng nhập người dùng bằng cách gửi tin nhắn SMS đến điện thoại của người dùng. Người dùng đăng nhập bằng mã một lần có trong Tin nhắn SMS.

Cách dễ nhất để thêm thông tin đăng nhập bằng số điện thoại vào ứng dụng của bạn là sử dụng FirebaseUI, bao gồm một tiện ích đăng nhập giúp triển khai quy trình đăng nhập cho điện thoại đăng nhập bằng số cũng như đăng nhập liên kết và dựa trên mật khẩu. Tài liệu này mô tả cách triển khai quy trình đăng nhập bằng số điện thoại bằng Firebase SDK.

Trước khi bắt đầu

Sao chép đoạn mã khởi chạy từ Firebase bảng điều khiển vào dự án của bạn như được mô tả trong Thêm Firebase vào dự án JavaScript của bạn.

Các mối lo ngại về bảo mật

Xác thực chỉ dùng số điện thoại, mặc dù thuận tiện nhưng lại kém an toàn so với các phương thức hiện có khác, do sở hữu số điện thoại có thể dễ dàng chuyển giữa những người dùng. Ngoài ra, trên các thiết bị có nhiều người dùng hồ sơ, bất kỳ người dùng nào có thể nhận tin nhắn SMS đều có thể đăng nhập vào tài khoản bằng số điện thoại của thiết bị.

Nếu bạn sử dụng tính năng đăng nhập dựa trên số điện thoại trong ứng dụng của mình, bạn sẽ cung cấp tính năng này cùng với các phương thức đăng nhập an toàn hơn và thông báo cho người dùng về tính bảo mật đánh đổi khi sử dụng đăng nhập bằng số điện thoại.

Bật tính năng đăng nhập bằng số điện thoại cho dự án Firebase của bạn

Để đăng nhập người dùng bằng SMS, trước tiên bạn phải bật tính năng đăng nhập bằng số điện thoại cho dự án Firebase của bạn:

  1. Trong bảng điều khiển Firebase, hãy mở phần Xác thực.
  2. Trên trang Phương thức đăng nhập, bật Số điện thoại đăng nhập.
  3. Trên cùng một trang, nếu miền sẽ lưu trữ ứng dụng của bạn không được liệt kê trong Miền chuyển hướng OAuth, thêm miền của bạn. Lưu ý rằng localhost không được cho phép dưới dạng một máy chủ lưu trữ nhằm mục đích xác thực qua điện thoại.

Thiết lập trình xác minh reCAPTCHA

Trước khi có thể đăng nhập người dùng bằng số điện thoại của họ, bạn phải thiết lập Trình xác minh reCAPTCHA của Firebase. Firebase sử dụng reCAPTCHA để ngăn chặn hành vi sai trái, chẳng hạn như bằng cách đảm bảo rằng yêu cầu xác minh số điện thoại đến từ một trong các miền được phép của ứng dụng.

Bạn không cần phải thiết lập ứng dụng reCAPTCHA theo cách thủ công; khi bạn sử dụng Đối tượng RecaptchaVerifier của Firebase SDK, Firebase tự động tạo và xử lý mọi khoá và khoá bí mật cần thiết của ứng dụng khách.

Đối tượng RecaptchaVerifier hỗ trợ ẩn reCAPTCHA, thường có thể xác minh người dùng mà không yêu cầu bất kỳ người dùng nào cũng như tiện ích reCAPTCHA, vốn luôn yêu cầu người dùng tương tác để hoàn tất thành công.

reCAPTCHA được kết xuất cơ bản có thể được bản địa hoá theo lựa chọn ưu tiên của người dùng bằng cách cập nhật mã ngôn ngữ trên thực thể Xác thực trước khi hiển thị reCAPTCHA. Bản địa hoá nói trên cũng sẽ áp dụng cho tin nhắn SMS được gửi đến người dùng, chứa mã xác minh.

Web

import { getAuth } from "firebase/auth";

const auth = getAuth();
auth.languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// auth.useDeviceLanguage();

Web

firebase.auth().languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

Sử dụng reCAPTCHA vô hình

Để sử dụng reCAPTCHA vô hình, hãy tạo đối tượng RecaptchaVerifier với tham số size được đặt thành invisible, chỉ định mã của nút gửi biểu mẫu đăng nhập. Ví dụ:

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Sử dụng tiện ích reCAPTCHA

Để sử dụng tiện ích reCAPTCHA hiển thị, hãy tạo một phần tử trên trang của bạn để chứa tiện ích này rồi tạo đối tượng RecaptchaVerifier, chỉ định mã vùng chứa khi bạn thực hiện việc này. Ví dụ:

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');

Không bắt buộc: Chỉ định tham số reCAPTCHA

Bạn có thể tuỳ ý đặt hàm callback trên Đối tượng RecaptchaVerifier được gọi khi người dùng giải quyết reCAPTCHA hoặc reCAPTCHA hết hạn trước khi người dùng gửi biểu mẫu:

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Không bắt buộc: Kết xuất trước reCAPTCHA

Nếu bạn muốn kết xuất trước reCAPTCHA trước khi gửi yêu cầu đăng nhập, gọi render:

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Sau khi render phân giải, bạn sẽ nhận được mã tiện ích của reCAPTCHA. Mã này sẽ bạn có thể dùng để gọi điện đến API reCAPTCHA:

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Gửi mã xác minh đến điện thoại của người dùng

Để bắt đầu đăng nhập bằng số điện thoại, hãy hiển thị cho người dùng một giao diện nhắc họ cần cung cấp số điện thoại, sau đó gọi signInWithPhoneNumber để yêu cầu Firebase gửi mã xác thực đến điện thoại của người dùng qua SMS:

  1. Lấy số điện thoại của người dùng.

    Các yêu cầu pháp lý có thể khác nhau, nhưng đây là phương pháp hay nhất và để đặt kỳ vọng cho người dùng, bạn nên cho họ biết rằng nếu họ sử dụng đăng nhập bằng điện thoại, họ có thể nhận được tin nhắn SMS để xác minh và gửi có áp dụng cước phí.

  2. Gọi signInWithPhoneNumber, truyền đến điện thoại của người dùng và RecaptchaVerifier mà bạn đã tạo trước đó.

    Web

    import { getAuth, signInWithPhoneNumber } from "firebase/auth";
    
    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    
    const auth = getAuth();
    signInWithPhoneNumber(auth, phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });

    Web

    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });
    Nếu signInWithPhoneNumber dẫn đến lỗi, hãy đặt lại reCAPTCHA để người dùng có thể thử lại:
    grecaptcha.reset(window.recaptchaWidgetId);
    
    // Or, if you haven't stored the widget ID:
    window.recaptchaVerifier.render().then(function(widgetId) {
      grecaptcha.reset(widgetId);
    });

Phương thức signInWithPhoneNumber đưa ra thử thách reCAPTCHA cho người dùng và nếu người dùng vượt qua thử thách, hãy yêu cầu Firebase Authentication gửi tin nhắn SMS chứa mã xác minh tới điện thoại của người dùng.

Đăng nhập người dùng bằng mã xác minh

Sau khi thực hiện lệnh gọi đến signInWithPhoneNumber thành công, hãy nhắc người dùng nhập mã xác minh họ nhận được qua SMS. Sau đó, đăng nhập người dùng bằng cách truyền mã này vào phương thức confirm của Đối tượng ConfirmationResult đã được truyền đến Trình xử lý phương thức thực hiện của signInWithPhoneNumber (tức là khối then). Ví dụ:

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Nếu lệnh gọi đến confirm thành công thì người dùng đã thực hiện thành công đã đăng nhập.

Lấy đối tượng AuthCredential trung gian

Nếu bạn cần lấy đối tượng AuthCredential cho chuyển mã xác minh từ kết quả xác nhận và gửi mã xác minh đến PhoneAuthProvider.credential thay vì đang gọi confirm:

var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);

Sau đó, bạn có thể đăng nhập cho người dùng bằng thông tin đăng nhập:

firebase.auth().signInWithCredential(credential);

Thử nghiệm bằng số điện thoại giả định

Bạn có thể thiết lập số điện thoại giả định để phát triển thông qua bảng điều khiển của Firebase. Kiểm thử bằng điện thoại hư cấu số mang lại các lợi ích sau:

  • Kiểm tra việc xác thực số điện thoại mà không làm tiêu tốn hạn mức sử dụng.
  • Kiểm tra xác thực số điện thoại mà không cần gửi tin nhắn SMS thực.
  • Chạy các thử nghiệm liên tiếp cho cùng một số điện thoại mà không bị điều tiết. Chiến dịch này giảm thiểu nguy cơ bị từ chối trong quá trình xem xét trên Cửa hàng ứng dụng nếu nhân viên đánh giá sử dụng cùng một số điện thoại để thử nghiệm.
  • Dễ dàng thử nghiệm trong các môi trường phát triển mà không cần làm gì thêm, chẳng hạn như khả năng phát triển trong trình mô phỏng iOS hoặc trình mô phỏng Android mà không cần Dịch vụ Google Play.
  • Viết mã kiểm thử tích hợp mà không bị chặn bởi các quy trình kiểm tra bảo mật thường áp dụng số điện thoại thực trong môi trường sản xuất.

Số điện thoại hư cấu phải đáp ứng các yêu cầu sau:

  1. Đảm bảo bạn sử dụng số điện thoại thực sự là giả tưởng và chưa tồn tại. Firebase Authentication không cho phép bạn đặt số điện thoại hiện có mà người dùng thực sử dụng làm số thử nghiệm. Một lựa chọn là sử dụng số có tiền tố 555 làm số điện thoại thử nghiệm ở Hoa Kỳ, ví dụ: +1 650-555-3434
  2. Số điện thoại phải được định dạng chính xác về độ dài và hạn chế. Chúng vẫn sẽ được xác thực giống như số điện thoại của người dùng thực.
  3. Bạn có thể thêm tối đa 10 số điện thoại để phát triển.
  4. Sử dụng số điện thoại/mã thử nghiệm khó đoán và thay đổi được những thông tin đó thường xuyên.

Tạo số điện thoại giả và mã xác minh

  1. Trong bảng điều khiển Firebase, hãy mở Mục Xác thực.
  2. Trong thẻ Phương thức đăng nhập, hãy bật Nhà cung cấp dịch vụ điện thoại nếu bạn chưa bật.
  3. Mở trình đơn đàn phong cầm Số điện thoại để thử nghiệm.
  4. Cung cấp số điện thoại mà bạn muốn kiểm tra, ví dụ: +1 650-555-3434.
  5. Hãy cung cấp mã xác minh gồm 6 chữ số cho số điện thoại cụ thể đó, ví dụ: 654321.
  6. Thêm số điện thoại. Nếu cần thiết, bạn có thể xoá số điện thoại và mã bằng cách di chuột qua hàng tương ứng và nhấp vào biểu tượng thùng rác.

Kiểm thử theo cách thủ công

Bạn có thể trực tiếp bắt đầu sử dụng một số điện thoại hư cấu trong đơn đăng ký của mình. Điều này cho phép bạn thực hiện kiểm thử thủ công trong các giai đoạn phát triển mà không gặp phải vấn đề về hạn mức hoặc điều tiết. Bạn cũng có thể kiểm thử trực tiếp từ trình mô phỏng iOS hoặc trình mô phỏng Android mà không cần Dịch vụ Google Play .

Khi bạn cung cấp số điện thoại giả và gửi mã xác minh, không có tin nhắn SMS thực nào được cung cấp đã gửi. Thay vào đó, bạn cần cung cấp mã xác minh đã định cấu hình trước đó để hoàn tất việc ký tên trong năm

Khi hoàn tất đăng nhập, người dùng Firebase sẽ được tạo bằng số điện thoại đó. Chiến lược phát hành đĩa đơn người dùng có hành vi và thuộc tính giống như người dùng số điện thoại thực và có thể truy cập Realtime Database/Cloud Firestore và các dịch vụ khác theo cùng cách. Mã thông báo mã nhận dạng đã được tạo trong khoảng thời gian quy trình này có cùng chữ ký với người dùng số điện thoại thực.

Một lựa chọn khác là đặt vai trò thử nghiệm thông qua tuỳ chỉnh xác nhận quyền sở hữu đối với những người dùng này để phân biệt họ là người dùng giả mạo nếu bạn muốn hạn chế hơn nữa truy cập.

Kiểm thử tích hợp

Ngoài việc kiểm thử thủ công, Firebase Authentication còn cung cấp các API để giúp viết chương trình kiểm thử tích hợp để kiểm tra tính xác thực của điện thoại. Các API này vô hiệu hoá tính năng xác minh ứng dụng bằng cách tắt reCAPTCHA trong web và thông báo đẩy im lặng trong iOS. Điều này giúp thử nghiệm tự động hoá có thể các quy trình này và dễ triển khai hơn. Ngoài ra, chúng giúp khả năng thử nghiệm phiên bản tức thì quy trình xác minh trên Android.

Trên web, hãy đặt appVerificationDisabledForTesting thành true trước khi kết xuất firebase.auth.RecaptchaVerifier. Thao tác này sẽ giải quyết reCAPTCHA tự động, cho phép bạn truyền số điện thoại mà không cần phải giải quyết theo cách thủ công. Ghi chú mặc dù reCAPTCHA đã bị tắt, việc sử dụng số điện thoại không hư cấu vẫn sẽ không thực hiện được hoàn tất đăng nhập. Bạn chỉ có thể sử dụng các số điện thoại hư cấu với API này.

// Turn off phone auth app verification.
firebase.auth().settings.appVerificationDisabledForTesting = true;

var phoneNumber = "+16505554567";
var testVerificationCode = "123456";

// This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true.
// This will resolve after rendering without app verification.
var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
// signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake
// reCAPTCHA response.
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
    .then(function (confirmationResult) {
      // confirmationResult can resolve with the fictional testVerificationCode above.
      return confirmationResult.confirm(testVerificationCode)
    }).catch(function (error) {
      // Error; SMS not sent
      // ...
    });

Trình xác minh ứng dụng reCAPTCHA vô hình và hiển thị hoạt động khác nhau khi quy trình xác minh ứng dụng đã tắt:

  • reCAPTCHA hiển thị: Khi reCAPTCHA hiển thị được hiển thị qua appVerifier.render(), nó sẽ tự động tự phân giải sau một phần nhỏ của giây chậm trễ. Điều này tương đương với việc người dùng nhấp vào reCAPTCHA ngay sau khi kết xuất. reCAPTCHA phản hồi sẽ hết hạn sau một khoảng thời gian và sau đó tự động giải quyết lại.
  • reCAPTCHA vô hình: reCAPTCHA vô hình không tự động phân giải khi kết xuất và thay vào đó tự động phân giải trên appVerifier.verify()gọi hoặc khi nút neo của reCAPTCHA được được nhấp sau một phần nhỏ độ trễ. Tương tự, phản hồi sẽ hết hạn sau một khoảng thời gian và sẽ chỉ tự động giải quyết sau lệnh gọi appVerifier.verify() hoặc khi nút neo của reCAPTCHA được nhấp lại.

Bất cứ khi nào một reCAPTCHA mô phỏng được giải quyết, hàm callback tương ứng sẽ được kích hoạt như dự kiến bằng phản hồi giả mạo. Nếu bạn cũng chỉ định lệnh gọi lại khi hết hạn, lệnh gọi lại đó sẽ kích hoạt khi hết hạn.

Các bước tiếp theo

Sau khi người dùng đăng nhập lần đầu tiên, một tài khoản người dùng mới sẽ được tạo và được liên kết với thông tin đăng nhập—tức là tên người dùng và mật khẩu, số điện thoại số hoặc thông tin của nhà cung cấp dịch vụ xác thực – người dùng đã đăng nhập. Thông tin mới này được lưu trữ như một phần của dự án Firebase và có thể được dùng để xác định một người dùng trên mọi ứng dụng trong dự án của bạn, bất kể người dùng đăng nhập bằng cách nào.

  • Trong ứng dụng của mình, bạn nên sử dụng cách để biết trạng thái xác thực của người dùng đặt trình quan sát trên đối tượng Auth. Sau đó, bạn có thể lấy thông tin thông tin hồ sơ cơ bản qua đối tượng User. Xem Quản lý người dùng.

  • Trong Firebase Realtime DatabaseCloud Storage của bạn Quy tắc bảo mật, bạn có thể lấy mã nhận dạng người dùng duy nhất của người dùng đã đăng nhập từ biến auth, để kiểm soát loại dữ liệu mà người dùng có thể truy cập.

Bạn có thể cho phép người dùng đăng nhập vào ứng dụng của mình bằng nhiều phương thức xác thực bằng cách liên kết thông tin đăng nhập của nhà cung cấp dịch vụ xác thực với tài khoản người dùng hiện có.

Để đăng xuất một người dùng, hãy gọi signOut:

Web

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});