diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fd4270a5..c1fa776e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ User-visible changes worth mentioning. - [#1662] Specify uri_redirect validation class explicitly. - [#1652] Add custom attributes support to token generator. - [#1667] Pass `client` instead of `grant.application` to `find_or_create_access_token`. +- [#1673] Honor `custom_access_token_attributes` in client credentials grant flow. ## 5.6.6 diff --git a/lib/doorkeeper/oauth/client_credentials/issuer.rb b/lib/doorkeeper/oauth/client_credentials/issuer.rb index e1999ffc6..78315946c 100644 --- a/lib/doorkeeper/oauth/client_credentials/issuer.rb +++ b/lib/doorkeeper/oauth/client_credentials/issuer.rb @@ -11,9 +11,9 @@ def initialize(server, validator) @validator = validator end - def create(client, scopes, creator = Creator.new) + def create(client, scopes, attributes = {}, creator = Creator.new) if validator.valid? - @token = create_token(client, scopes, creator) + @token = create_token(client, scopes, attributes, creator) @error = :server_error unless @token else @token = false @@ -25,7 +25,7 @@ def create(client, scopes, creator = Creator.new) private - def create_token(client, scopes, creator) + def create_token(client, scopes, attributes, creator) context = Authorization::Token.build_context( client, Doorkeeper::OAuth::CLIENT_CREDENTIALS, @@ -39,6 +39,7 @@ def create_token(client, scopes, creator) scopes, use_refresh_token: false, expires_in: ttl, + **attributes ) end end diff --git a/lib/doorkeeper/oauth/client_credentials_request.rb b/lib/doorkeeper/oauth/client_credentials_request.rb index 93b3aaba0..4b0f1d794 100644 --- a/lib/doorkeeper/oauth/client_credentials_request.rb +++ b/lib/doorkeeper/oauth/client_credentials_request.rb @@ -3,7 +3,7 @@ module Doorkeeper module OAuth class ClientCredentialsRequest < BaseRequest - attr_reader :client, :original_scopes, :response + attr_reader :client, :original_scopes, :parameters, :response alias error_response response @@ -14,6 +14,7 @@ def initialize(server, client, parameters = {}) @server = server @response = nil @original_scopes = parameters[:scope] + @parameters = parameters.except(:scope) end def access_token @@ -30,7 +31,14 @@ def issuer private def valid? - issuer.create(client, scopes) + issuer.create(client, scopes, custom_token_attributes_with_data) + end + + def custom_token_attributes_with_data + parameters + .with_indifferent_access + .slice(*Doorkeeper.config.custom_access_token_attributes) + .symbolize_keys end end end diff --git a/spec/lib/oauth/client_credentials/issuer_spec.rb b/spec/lib/oauth/client_credentials/issuer_spec.rb index 2a39c51ba..06ff00a22 100644 --- a/spec/lib/oauth/client_credentials/issuer_spec.rb +++ b/spec/lib/oauth/client_credentials/issuer_spec.rb @@ -24,7 +24,7 @@ it "creates and sets the token" do expect(creator).to receive(:call).and_return("token") - issuer.create client, scopes, creator + issuer.create client, scopes, {}, creator expect(issuer.token).to eq("token") end @@ -37,12 +37,24 @@ use_refresh_token: false, ) - issuer.create client, scopes, creator + issuer.create client, scopes, {}, creator + end + + it "creates with custom token parameters" do + expect(creator).to receive(:call).with( + client, + scopes, + expires_in: 100, + use_refresh_token: false, + tenant_id: 9000 + ) + + issuer.create client, scopes, { tenant_id: 9000 }, creator end it "has error set to :server_error if creator fails" do expect(creator).to receive(:call).and_return(false) - issuer.create client, scopes, creator + issuer.create client, scopes, {}, creator expect(issuer.error).to eq(:server_error) end @@ -55,12 +67,12 @@ it "has error set from validator" do expect(creator).not_to receive(:create) - issuer.create client, scopes, creator + issuer.create client, scopes, {}, creator expect(issuer.error).to eq(:validation_error) end it "returns false" do - expect(issuer.create(client, scopes, creator)).to be_falsey + expect(issuer.create(client, scopes, {}, creator)).to be_falsey end end @@ -93,7 +105,7 @@ expires_in: custom_ttl_grant, use_refresh_token: false, ) - issuer.create client, scopes, creator + issuer.create client, scopes, {}, creator end it "respects scope based rules" do @@ -103,7 +115,7 @@ expires_in: custom_ttl_scope, use_refresh_token: false, ) - issuer.create client, custom_scope, creator + issuer.create client, custom_scope, {}, creator end end end diff --git a/spec/lib/oauth/client_credentials_request_spec.rb b/spec/lib/oauth/client_credentials_request_spec.rb index 4c4419682..4c6dd5160 100644 --- a/spec/lib/oauth/client_credentials_request_spec.rb +++ b/spec/lib/oauth/client_credentials_request_spec.rb @@ -23,7 +23,7 @@ end it "issues an access token for the current client" do - expect(token_creator).to receive(:create).with(client, nil) + expect(token_creator).to receive(:create).with(client, nil, {}) request.authorize end @@ -57,14 +57,29 @@ end it "issues an access token with default scopes if none was requested" do - expect(token_creator).to receive(:create).with(client, default_scopes) + expect(token_creator).to receive(:create).with(client, default_scopes, {}) request.authorize end it "issues an access token with requested scopes" do request = described_class.new(server, client, scope: "email") allow(request).to receive(:issuer).and_return(token_creator) - expect(token_creator).to receive(:create).with(client, Doorkeeper::OAuth::Scopes.from_string("email")) + expect(token_creator).to receive(:create).with(client, Doorkeeper::OAuth::Scopes.from_string("email"), {}) + request.authorize + end + end + + context "with custom_access_token_attributes configured" do + before do + Doorkeeper.configure do + custom_access_token_attributes [:tenant_id] + end + end + + it "issues an access token with the custom access token attributes" do + request = described_class.new(server, client, scope: "email", tenant_id: 9000) + allow(request).to receive(:issuer).and_return(token_creator) + expect(token_creator).to receive(:create).with(client, Doorkeeper::OAuth::Scopes.from_string("email"), { tenant_id: 9000 }) request.authorize end end