Skip to content

Instantly share code, notes, and snippets.

@elchingon
Forked from thibaudgg/HTTP.md
Created May 19, 2021 19:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elchingon/484349fd1df0a0d0ebbd0f4b4b76083b to your computer and use it in GitHub Desktop.
Save elchingon/484349fd1df0a0d0ebbd0f4b4b76083b to your computer and use it in GitHub Desktop.
# app/models/doorkeeper/access_token.rb
module Doorkeeper
class AccessToken < ActiveRecord::Base
belongs_to :resource_owner, class_name: 'OauthResourceOwner'
def as_json(*)
super.except!(:resource_owner_id).merge!(
owner: {
id: resource_owner&.owner_id,
type: resource_owner&.owner_type&.tableize
}
)
end
end
end
# config/doorkeeper.rb
Doorkeeper.configure do
orm :active_record
# ...
resource_owner_from_credentials do |_routes|
app = Doorkeeper::Application.by_uid(params[:client_id])
OauthResourceOwnerAuthenticator.authenticate(app, request) if app
end
# ...
end
POST /oauth/token HTTP/1.1
Content-Type: application/json

{
  "grant_type": "password",
  "client_id": "CLIENT_ID",
  "owner_type": "OWNER_TYPE",
  "username": "OWNER_EMAIL",
  "password": "OWNER_PASSWORD"
}
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "access_token": "e2892936f4...3a0d3171b0",
  "token_type": "bearer",
  "expires_in": 7200,
  "refresh_token": "6231777801...735af7da27",
  "created_at": 1430921359,
  "owner_id": "OWNER_ID",
  "owner_type": "OWNER_TYPE"
}
# app/models/oauth_resource_owner.rb
class OauthResourceOwner < ActiveRecord::Base
belongs_to :owner, polymorphic: true
end
# app/services/oauth_resource_owner_authenticator.rb
class OauthResourceOwnerAuthenticator
attr_reader :application, :request
delegate :params, to: :request
def self.authenticate(*args)
new(*args).authenticate
end
def initialize(application, request)
@application = application
@request = request
end
def authenticate
return unless owner_class
owner = authenticate_owner
OauthResourceOwner.find_or_create_by(owner: owner) if owner
end
private
def authenticate_owner
owner = owner_class.find_for_database_authentication(
email: params[:username]
)
return unless owner&.valid_password?(params[:password])
update_tracked_fields(owner)
owner
end
# Update Devise tracked fields
def update_tracked_fields(owner)
if owner.respond_to?(:update_tracked_fields!)
owner.update_tracked_fields!(request)
end
end
def owner_class
case params[:owner_type]
when /admin/i then Admin
when /user/i then User
end
end
end
# lib/doorkeeper/oauth/token_response_body_with_resource_owner.rb
module Doorkeeper
module OAuth
module TokenResponseBodyWithResourceOwner
def body
super.merge({
'owner_id' => token.resource_owner&.owner_id,
'owner_type' => token.resource_owner&.owner_type&.tableize
}.compact)
end
end
TokenResponse.prepend(TokenResponseBodyWithResourceOwner)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment