[Ruby on Rails] Đăng nhập bằng tài khoản Google với OmniAuth

Ngày nay, hầu hết các trang web đều cho phép người dùng đăng nhập bằng tài khoản mạng xã hội như Google, Twitter hay Facebook…Trong bài viết này, mình sẽ hướng dẫn mọi người cách thiết lập cho trang web của mình thực hiện tính năng này nhé. Cài đặt gem và cấu hình Đầu

Ngày nay, hầu hết các trang web đều cho phép người dùng đăng nhập bằng tài khoản mạng xã hội như Google, Twitter hay Facebook…Trong bài viết này, mình sẽ hướng dẫn mọi người cách thiết lập cho trang web của mình thực hiện tính năng này nhé.

Cài đặt gem và cấu hình

Đầu tiên, ta cài đặt các gem sau trong file Gemfile

gem "devise"
gem "omniauth"
gem "omniauth-google-oauth2"
gem "omniauth-rails_csrf_protection"

Thiết lập khai báo trong file: config/initializers/devise.rb:

config.omniauth :google_oauth2, ENV["GOOGLE_OAUTH_CLIENT_ID"], ENV["GOOGLE_OAUTH_CLIENT_SECRET"], {scope: "email"}

Trong đó, GOOGLE_OAUTH_CLIENT_ID và GOOGLE_OAUTH_CLIENT_SECRET là 2 biến môi trường được thiết lập trong file config/application.yml. Mình sẽ hướng dẫn cách các bạn lấy hai giá trị này ngay sau đây:

Đầu tiên các bạn vào link sau:
https://console.developers.google.com

Chọn CREATE PROJECT
Sau khi tạo project thành công, bạn thiết lập các thông tin cần thiết tại Oauth consent screen.
Sau khi điền các thông tin cần thiết, chọn Credentials > CREATE CREDENTISLS > Oauth client ID

Tại application type, chọn Web application

Sau khi tạo xong, một cửa sổ popup hiển thị lên với

Your Client ID là giá trị của ENV[“GOOGLE_OAUTH_CLIENT_ID”]

Your Client Secret là giá trị của ENV[“GOOGLE_OAUTH_CLIENT_SECRET”]

Thêm trường uid và provider vào model (ở đây mình giả sử model là User)

rails generate migration AddOmniauthToUsers provider:string uid:string name:string

Run rails db:migrate để thêm các trường này vào cơ sở dữ liệu

Cấu hình file routes.rb

Thêm dòng sau vào file:

devise_for :users, controllers: {omniauth_callbacks: "omniauth_callbacks"}

Nếu tại file routes, bạn có scope cho locale, thì dòng code này phải đề bên ngoài scope nhé.

Cấu hình controller

Tạo file mới tại app/controllers/omniauth_callbacks_controller.rb:

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google_oauth2
    @user = User.from_omniauth request.env["omniauth.auth"]

    if @user.persisted?
      flash[:notice] = "Successfully authenticated from Google account."
      sign_in_and_redirect @user, event: :authentication

    else
      session["devise.google_data"] = request.env["omniauth.auth"]
                                             .except("extra")
      redirect_to new_user_registration_url,
                  alert: @user.errors.full_messages.join("n")
    end
  end
end

Ở đây, có một vài thông số có thể bạn cảm thấy khó hiểu, vì vậy mình sẽ giải thích như sau:

  • request.env[“omniauth.auth”] : Tất cả thông tin được truy xuất từ Google bởi OmniAuth có sẵn dưới dạng băm tại đây
  • Khi tìm thấy người dùng hợp lệ, họ có thể đăng nhập bằng một trong hai phương thức của Devise: sign_in hoặc sign_in_and_redirect, thông qua event: :authentication
  • Trong trường hợp người dùng không còn tồn tại, sẽ lưu trữ dữ liệu OmniAuth trong session.
  • Cuối cùng, sẽ chuyển hướng user trở lại form đăng ký.

Cấu hình Model

Sau khi xử lý ở Controller, chúng ta tiến hành triển khai tại Model User

def self.from_omniauth access_token
    data = access_token.info
    User.where(email: data["email"])
           .first_or_create(email: data["email"],
                            password: Devise.friendly_token[0, 20],
                            provider: access_token[:provider],
                            uid: access_token[:uid])
  end

Method này sẽ tìm người dùng theo các thuộc tính được truyền vào (tại hàm where). Sau đó, tiếp tục gọi hàm first_or_create, để nếu không tìm thấy user sẽ tạo user đó với các thuộc tính đã truyền vào, hoặc các thuộc tính khác được cấp. Password sẽ được tạo ngẫu nhiên bởi gem Devise.

Cấu hình view

Tại app/view/users/sessions/new.html.erb . Thêm:

<%- if devise_mapping.omniauthable? %>
  <%- resource_class.omniauth_providers.each do |provider| %>
    <%= link_to "Sign in with Google", omniauth_authorize_path(resource_name, provider), method: :post %>
  <% end %>
<% end %>

Cấu hình đã xong, bây giờ thì rails s và trải nghiệm thôi nào!

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ