Doorkeeper is an OAuth 2 provider for Rails

I. Cài đặt

  • Doorkeeper là một gem làm cho bạn dễ dàng tương tác chức năng của nhà cung cấp OAuth 2 đối với ứng dụng Rails hoặc Grape của bạn.
  • Thêm vào Gemfile
      gem 'doorkeeper' 
    
  • Chạy lệnh để khởi tạo:
    rails generate doorkeeper:install
    
  • Thao tác này sẽ cài đặt trình khởi tạo doorkeeper vào config/initializers/doorkeeper.rb
  • Configuration
    • Theo mặc địch của doorkeeper sử dụng active record, ta có thể bắt đầu tạo các migration: rails generate doorkeeper:migration
    • Routes
    Rails.application.routes.draw do
     use_doorkeeper
     # your routes
    end
    
    => Điều này sẽ gắn kết các routes như sau:
    GET       /oauth/authorize/:code
    GET       /oauth/authorize
    POST      /oauth/authorize
    DELETE    /oauth/authorize
    POST      /oauth/token
    POST      /oauth/revoke
    resources /oauth/applications
    GET       /oauth/authorized_applications
    DELETE    /oauth/authorized_applications/:id
    GET       /oauth/token/info
    
    • Authenticating
      • Bạn cần phải cấu hình Doorkeeper để cung cấp mô hình resource_owner và khối xác thực trong config/initializers/doorkeeper.rb
      resource_owner_authenticator do
        warden.authenticate!(scope: :user)
      end
      resource_owner_from_credentials do |routes|
        user = User.find_by email: params[:email]
        user if user && user.valid_password?(params[:password])
      end
      
    • Sử dụng OAuth trong Rails #app/controllers/api/v1/base_controller.rb
       class Api::V1::BaseController < ActionController::API
          clear_respond_to
          respond_to :json
          before_action :doorkeeper_authorize!
          before_action :authenticate_user!
      
          private
          def authenticate_user!
            if doorkeeper_token
              Thread.current[:current_user] = User.find doorkeeper_token.resource_owner_id
            end
            return if current_user
            render json: { errors: ["User is not authenticated!"] }, status: :unauthorized
          end
      
          def current_user
            Thread.current[:current_user]
          end
      
          def errors_json messages
            { errors: [*messages] }
          end
        end
      
      • Bạn có thể bất kỳ tuỳ chọn để vượt qua before_action, chẳng hạn như if, only, except...
      class Api::V1::UsersController < Api::V1::BaseController
        skip_before_action :doorkeeper_authorize!, only: :create
        skip_before_action :authenticate_user!, only: :create
        ...............
      end
      
    • Sử dụng OAuth với Grape
      • Theo PR 567 doorkeeper đã hỗ trợ cho Grape >= 0.10. Một trong số đó là doorkeeper_authorize!. Và có thể được sử dụng theo cách tương tự như ví dụ trên. Chú ý bạn phải sử dụng doorkeeper/grape/helpers và helpers Doorkeeper::Grape::Helpers.
      require 'doorkeeper/grape/helpers'
      
       module API
         module V1
           class Users < Grape::API
             helpers Doorkeeper::Grape::Helpers
      
             before do
               doorkeeper_authorize!
             end
      
             route_setting :scopes, ['user:email']
             get :emails do
               [{email: current_user.email}]
             end
      
             # ...
           end
         end
       end
      
  • Tùy chỉnh hết hạn Token
    • Access Grant: Mặc định thời gian hết hạn của access grant là 10 phút, ta có thể thay đổi trong file config.
       Doorkeeper.configure do
         authorization_code_expires_in 20.minutes
       end
      
    • Access Token Mặc định thời gian hết hạn của token là 2 giờ, ta có thể thay đổi nó tương tự access grant
       Doorkeeper.configure do
         access_token_expires_in 4.hours
       end
      
    • Refresh Token Không giống như access grant hay token refresh_token không có thời gian hết hạn
      RestClient.post "localhost:3000/api/v1/oauth/[email protected]&password=12345678&grant_type=password"
      
      =>
      {
        "access_token": "2746a4a7a720ee1593c26f3c033a4c1a0b51c9dfefe4d0bd99c494e8acc445fb",
        "token_type": "bearer",
        "expires_in": 7199,
        "refresh_token": "7da7b68d957fa475cf5d56b01c33385794edfb246cb2db509ecb79785a703705",
        "created_at": 1503903600
      }