Last active
October 27, 2021 06:22
-
-
Save thibaudgg/3aa7e3276fbcdd712cbf to your computer and use it in GitHub Desktop.
Polymorphic ResourceOwner support (https://github.com/doorkeeper-gem/doorkeeper/issues/651#issuecomment-99880425)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/oauth_resource_owner.rb | |
class OauthResourceOwner < ActiveRecord::Base | |
belongs_to :owner, polymorphic: true | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
Hi, don`t forget the migration:
class CreateOauthResourceOwners < ActiveRecord::Migration
def change
create_table :oauth_resource_owners do |t|
t.string :owner_type
t.integer :owner_id
t.timestamps null: false
end
end
end
Thank you so much for this!
Great work @thibaudgg! Do you have news about this feature and doorkeeper? Are you still using this workaround?
If I check the Doorkeeper::AccessToken
associations in rails console:
Doorkeeper::AccessToken.reflect_on_all_associations.map(&:name)
it results only with application
and without resource_owner
. Any idea why? I have added exactly the model like described here (app/models/doorkeeper/access_token.rb).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Kudos for this!
Any problems you've uncovered?