Tích hợp xác thực số điện thoại với FireBase – Hoàng Web

Trong hướng dẫn này, mình sẽ hướng dẫn bạn tạo đăng nhập bằng xác thực số điện thoại người dùng với Firebase. Tải code tại  repo này.

Firebase Phone Number authentication cung cấp một hình thức xác thực mật mã, trong đó người dùng được chứng thực về quyền truy cập trên một nền tảng an toàn của họ, thay vì chứng thực dựa trên mật khẩu đơn thuần.

Nền tảng an toàn trong trường hợp với Firebase  là điện thoại di động của người dùng. Xác thực đòi hỏi người sử dụng phải có số điện thoại di động chính xác và điện thoại của họ. Tuy nhiên, xác thực chỉ sử dụng một số điện thoại cũng có thể là kém an toàn hơn so với các phương pháp có sẵn khác vì sở hữu một số điện thoại có thể dễ dàng chuyển giữa các người dùng.

Các bước xác thực với Firebase

Quy trình xác thực với các bước sau.

  • Một người sử dụng đăng nhập vào ứng dụng web của bạn và có 1 trường yêu cầu họ nhập số điện thoại.
  • Firebase’s reCAPTCHA verifier sẽ xác minh tính hợp lệ bằng cách đảm bảo số điện thoại được xác thực từ ứng dụng trên domain đã đăng ký.
  • Một Khi người dùng nhấp vào  Log In    , mã xác minh sẽ được gửi đến điện thoại của người dùng thông qua SMS.
  • Người dùng nhập lại mã code này trên web.
  • Firebase xác nhận mã code có hợp lệ không. Nếu đúng, một tài khoản người dùng mới được tạo ra và liên kết với số điện thoại đó.

Cấu hình xác thực số điện thoại với Firebase

Nếu bạn chưa có tài khoản Firebase, đăng ký một tài khoản miễn phí.

  • Tạo một dự án mới
  • Mở phần Authentication ở thanh bên trái.
  • Trên trang Sign-in Method, kích hoạt phương thức Phone Number sign-in.
  • Đảm bảo rằng tên miền của bạn được liệt kê trong phần Authorized Domains . localhost     được thêm vào mặc định.

Bước 1: Firebase Config

Trong thư mục dự án mới của bạn, tạo file  index.html . Bây giờ, quay trở lại màn hình tổng quan của project và click vào nó. Sau đó bấm Add Firebase to your Web app . Một popup sẽ hiển thị như sau:

Popup

Sao chép code và dán nó vào tệp  index.html như thế này:




  <meta charset="UTF-8">
  <title>Firebase Phone Authentication</title>
  <script src="https://www.gstatic.com/firebasejs/4.3.1/firebase.js"></script>
  <script>
    // Initialize Firebase
    var config = {
      apiKey: "AIzaSyDGQQUw4xRJagflxcmct5k5Bqgc4x1_Yik",
      authDomain: "phoneauth-bbe99.firebaseapp.com",
      databaseURL: "https://phoneauth-bbe99.firebaseio.com",
      projectId: "phoneauth-bbe99",
      storageBucket: "phoneauth-bbe99.appspot.com",
      messagingSenderId: "1071451028890"
    };
    firebase.initializeApp(config);
  </script>
  <script src="https://cdn.firebase.com/libs/firebaseui/2.3.0/firebaseui.js"></script>
  <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/2.3.0/firebaseui.css">
  <link href="style.css" rel="stylesheet" type="text/css" media="screen">




Lưu ý: nên sử dụng liên kết chính thức của thư viện Firebase và FirebaseUI. Thư viện FirebaseUI cung cấp các sử lý giao diện đơn giản, các sự kiện UI dựa trên Firebase SDK.

Tạo một file  style.css và chèn vào đoạn mã sau:

style.css

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

#container {
  max-width: 600px;
  margin: 0 auto;
  text-align: center;
}

.clearfix {
  clear: both;
}

.hidden {
  display: none;
}

#user-info {
  border: 1px solid #CCC;
  clear: both;
  margin: 0 auto 20px;
  max-width: 400px;
  padding: 10px;
  text-align: left;
}

#photo-container {
  background-color: #EEE;
  border: 1px solid #CCC;
  float: left;
  height: 80px;
  margin-right: 10px;
  width: 80px;
}

#photo {
  height: 80px;
  margin: 0;
  width: 80px;
}

@media (max-width: 300px) {
  #photo-container,
  #photo {
    height: 40px;
    width: 40px;
  }
}

Bước 2: Viết HTML

Sửa file  index.html và chèn vào đoạn code dưới đây:

<div id="container">
      <h3>Firebase Phone Number Auth. Demo</h3>
      <div id="loading">Loading...</div>
      <div id="loaded" class="hidden">
        <div id="main">
          <div id="user-signed-in" class="hidden">
            <div id="user-info">
              <div id="photo-container">
                <img id="photo" class="">
              </div>
              <div id="name"></div>
              <div id="email"></div>
              <div id="phone"></div>
              <div class="clearfix"></div>
            </div>
            <p>
              <button id="sign-out">Sign Out</button>
              <button id="delete-account">Delete account</button>
            </p>
          </div>
          <div id="user-signed-out" class="hidden">
            <h4>You are signed out.</h4>
            <div id="firebaseui-spa">
              <h3>Single Page App mode:</h3>
              <div id="firebaseui-container"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <script src="app.js"></script>

Div  firebaseui-container sẽ chứa nút đăng nhập. File  app.js sẽ chứa mã logic của ứng dụng để sử lý xác thực. Và dẫn chúng ta đến giai đoạn tiếp theo.

Bước 3: Thiết lập số điện thoại xác thực

Tạo file  app.js và thêm mã dưới đây vào:

/**
 * @return {!Object} The FirebaseUI config.
 */
function getUiConfig() {
  return {
    'callbacks': {
      // Called when the user has been successfully signed in.
      'signInSuccess': function(user, credential, redirectUrl) {
        handleSignedInUser(user);
        // Do not redirect.
        return false;
      }
    },
    // Opens IDP Providers sign-in flow in a popup.
    'signInFlow': 'popup',
    'signInOptions': [
      // The Provider you need for your app. We need the Phone Auth
      firebase.auth.TwitterAuthProvider.PROVIDER_ID,
      {
        provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
        recaptchaParameters: {
          type: 'image', // another option is 'audio'
          size: 'invisible', // other options are 'normal' or 'compact'
          badge: 'bottomleft' // 'bottomright' or 'inline' applies to invisible.
        }
      }
    ],
    // Terms of service url.
    'tosUrl': 'https://www.google.com'
  };
}
// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());
/**
 * Displays the UI for a signed in user.
 * @param {!firebase.User} user
 */
var handleSignedInUser = function(user) {
  document.getElementById('user-signed-in').style.display = 'block';
  document.getElementById('user-signed-out').style.display = 'none';
  document.getElementById('name').textContent = user.displayName;
  document.getElementById('email').textContent = user.email;
  document.getElementById('phone').textContent = user.phoneNumber;
  if (user.photoURL){
    document.getElementById('photo').src = user.photoURL;
    document.getElementById('photo').style.display = 'block';
  } else {
    document.getElementById('photo').style.display = 'none';
  }
};
/**
 * Displays the UI for a signed out user.
 */
var handleSignedOutUser = function() {
  document.getElementById('user-signed-in').style.display = 'none';
  document.getElementById('user-signed-out').style.display = 'block';
  ui.start('#firebaseui-container', getUiConfig());
};
// Listen to change in auth state so it displays the correct UI for when
// the user is signed in or not.
firebase.auth().onAuthStateChanged(function(user) {
  document.getElementById('loading').style.display = 'none';
  document.getElementById('loaded').style.display = 'block';
  user 
 handleSignedInUser(user) : handleSignedOutUser();
});
/**
 * Deletes the user's account.
 */
var deleteAccount = function() {
  firebase.auth().currentUser.delete().catch(function(error) {
    if (error.code == 'auth/requires-recent-login') {
      // The user's credential is too old. She needs to sign in again.
      firebase.auth().signOut().then(function() {
        // The timeout allows the message to be displayed after the UI has
        // changed to the signed out state.
        setTimeout(function() {
          alert('Please sign in again to delete your account.');
        }, 1);
      });
    }
  });
};
/**
 * Initializes the app.
 */
var initApp = function() {
  document.getElementById('sign-out').addEventListener('click', function() {
    firebase.auth().signOut();
  });
  document.getElementById('delete-account').addEventListener(
      'click', function() {
        deleteAccount();
      });
};
window.addEventListener('load', initApp);

Hàm getUiConfig chịu trách nhiệm về việc cấu hình các nhà cung cấp chứng thực chúng ta muốn. Thêm các tùy chọnPhone NumberTwitter login . Và tùy chọn  reCaptchaParameters có cầu hình invisible reCaptcha.

Giá trị cho tham số reCaptchaParameters của reCaptcha gồm có:

  • type: lựa chọn các loại hình ảnh. Một lựa chọn khác là âm thanh.
  • size: kích thước bình thường(normal) hay nhỏ gọn (compact).
  • badge: chọn biểu tượng reCaptcha xuất hiện từ vị trí bottom-left, bottom-right hoặc inline

Hai hình thức đăng nhập  có tích hợp sẵn trong Firebase:

  • redirect:  (mặc định)  sẽ thực hiện một chuyển hướng đầy đủ đến trang đăng nhập của nhà cung cấp (Google, Facebook …). cách này được khuyến khích cho các ứng dụng di động.
  • popup:   sẽ mở ra một popup cho trang đăng nhập của nhà cung cấp. Nếu popup bị chặn bởi trình duyệt, nó sẽ tiếp tục chuyển hướng đến trang đăng nhập riêng.

Ví dụ dưới đây, chúng ta chọn  popup cho thuận tiện.

Thuộc tính đầu tiên trong getUiConfigcallbacks . signInSuccess là một trong những callbacks sẽ dùng. Đi kèm với tham số  currentUser , credentialredirectUrl trong hàm gọi handleSignedInUser .

Nếu callback trả về  false , có nghĩa là trang đó không được tự động chuyển hướng.

Dưới đây là nội dung của function  handleSignedInUser :

/**
 * Displays the UI for a signed in user.
 * @param {!firebase.User} user
 */
var handleSignedInUser = function(user) {
  document.getElementById('user-signed-in').style.display = 'block';
  document.getElementById('user-signed-out').style.display = 'none';
  document.getElementById('name').textContent = user.displayName;
  document.getElementById('email').textContent = user.email;
  document.getElementById('phone').textContent = user.phoneNumber;
  if (user.photoURL){
    document.getElementById('photo').src = user.photoURL;
    document.getElementById('photo').style.display = 'block';
  } else {
    document.getElementById('photo').style.display = 'none';
  }
};

Hàm hiển thị chi tiết thông tin người dùng trên màn hình. Func  handleSignedOutUser có chức năng tương tự nhưng khi dùng đăng xuất.

Hàm dưới đây chỉ đơn giản là theo dõi để thay đổi trạng thái xác thực và hiển thị giao diện người dùng phù hợp dựa trên những thay đổi đó.

firebase.auth().onAuthStateChanged(function(user) {
  document.getElementById('loading').style.display = 'none';
  document.getElementById('loaded').style.display = 'block';
  user 
 handleSignedInUser(user) : handleSignedOutUser();
});

Hàm  initApp  dùng khởi tạo sự kiện cho nút sign-out và delete-account . Khi người dùng nhấn vào các nút này , hàm sự kiện tương ứng của nó sẽ được kích hoạt.

var initApp = function() {
  document.getElementById('sign-out').addEventListener('click', function() {
    firebase.auth().signOut();
  });
  document.getElementById('delete-account').addEventListener(
      'click', function() {
        deleteAccount();
      });
};

Bước 4: Chạy ứng dụng

Lưu ý: Nút đăng nhập twitter không hoạt động. Chúng ta chỉ minh họa làm phong phú giao diện người dùng mà thôi. Trong ứng dụng chạy thật, nó là một tùy chọn thay thế.

  • Nhấp vào nút  Sign in with phone  .
    Sign in with Phone
      
  • Chọn quốc gia của bạn, nhập số điện thoại của bạn và nhấp Verify    .
    Form
      
  • Nhận mã ngắn được gửi bởi Firebase vào điện thoại của bạn.
      Auth0's SMS received
        
  • Nhập mã này vào trường xác minh   
    Input Short code
  • Bấm tiếp tục. Và đợi firebase xác minh. 
    Verify
     
  • Người dùng đăng nhập thành công. 
    LoggedIn User
     

Trong giao diện quản trị Firebase, tab  users sẽ thông báo cho bạn các người dùng đã thực hiện xác minh trên ứng dụng của bạn.

Firebase User Console      

Kết luận

Trong bài này bạn đã học được làm thế nào để tạo một xác thực người dùng sử dụng số điện thoại với Firebase. Bạn nên biết rằng số điện thoại mà người dùng cuối cùng cung cấp để xác thực sẽ được gửi và lưu trữ bởi Google để cải thiện ngăn chặn spam và lạm dụng của họ trên dịch vụ của Google.

Là một nhà phát triển ứng dụng, bạn cần đảm bảo rằng có sự đồng ý của người dùng cuối trước khi sử dụng dịch vụ đăng nhập xác thực qua số điện thoại của Firebase.

Một điều nữa. Để tránh lạm dụng, Firebase có giới hạn về số lượng tin nhắn SMS có thể được gửi đến một số điện thoại duy nhất trong một khoảng thời gian. Nếu bạn vượt quá giới hạn này, số điện thoại đó có thể bị khóa trong một thời gian. Nếu bạn gặp phải vấn đề này, hãy sử dụng các số điện thoại khác nhau để thử nghiệm, hoặc thử yêu cầu ở một thời điểm khác.

Nếu bạn có bất kỳ câu hỏi thắc mắc hãy để lại ý kiến dưới bài viết nhé. 😊