Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump doorkeeper 5.5 and define body method for authorization response to support response_mode=form_post #138

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Unreleased

- [#138] Support form_post response mode (This gem now requires Doorkeeper v5.5)

## v1.7.5 (2020-12-15)

### Changes
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The following parts of [OpenID Connect Core 1.0](http://openid.net/specs/openid-
- [Requesting Claims using Scope Values](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims)
- [UserInfo Endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo)
- [Normal Claims](http://openid.net/specs/openid-connect-core-1_0.html#NormalClaims)
- [OAuth 2.0 Form Post Response Mode](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)

In addition we also support most of [OpenID Connect Discovery 1.0](http://openid.net/specs/openid-connect-discovery-1_0.html) for automatic configuration discovery.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def provider_response

# TODO: support id_token response type
response_types_supported: doorkeeper.authorization_response_types,
response_modes_supported: %w[query fragment],
response_modes_supported: response_modes_supported(doorkeeper),
grant_types_supported: grant_types_supported(doorkeeper),

# TODO: look into doorkeeper-jwt_assertion for these
Expand Down Expand Up @@ -76,6 +76,10 @@ def grant_types_supported(doorkeeper)
grant_types_supported
end

def response_modes_supported(doorkeeper)
doorkeeper.authorization_response_flows.flat_map(&:response_mode_matches).uniq
end

def webfinger_response
{
subject: params.require(:resource),
Expand Down
2 changes: 1 addition & 1 deletion doorkeeper-openid_connect.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Gem::Specification.new do |spec|

spec.required_ruby_version = '>= 2.4'

spec.add_runtime_dependency 'doorkeeper', '>= 5.2', '< 5.5'
spec.add_runtime_dependency 'doorkeeper', '>= 5.5', '< 5.6'
toupeira marked this conversation as resolved.
Show resolved Hide resolved
spec.add_runtime_dependency 'json-jwt', '>= 1.11.0'

spec.add_development_dependency 'conventional-changelog', '~> 1.2'
Expand Down
12 changes: 5 additions & 7 deletions lib/doorkeeper/oauth/id_token_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,17 @@ def redirectable?
true
end

def redirect_uri
Authorization::URIBuilder.uri_with_fragment(pre_auth.redirect_uri, redirect_uri_params)
end

private

def redirect_uri_params
def body
{
expires_in: auth.token.expires_in_seconds,
state: pre_auth.state,
id_token: id_token.as_jws_token
}
end

def redirect_uri
Authorization::URIBuilder.uri_with_fragment(pre_auth.redirect_uri, body)
end
end
end
end
4 changes: 1 addition & 3 deletions lib/doorkeeper/oauth/id_token_token_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
module Doorkeeper
module OAuth
class IdTokenTokenResponse < IdTokenResponse
private

def redirect_uri_params
def body
super.merge({
access_token: auth.token.token,
token_type: auth.token.token_type
Expand Down
35 changes: 15 additions & 20 deletions lib/doorkeeper/openid_connect.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
require 'doorkeeper/openid_connect/claims/claim'
require 'doorkeeper/openid_connect/claims/normal_claim'
require 'doorkeeper/openid_connect/config'
require 'doorkeeper/openid_connect/response_types_config'
require 'doorkeeper/openid_connect/engine'
require 'doorkeeper/openid_connect/errors'
require 'doorkeeper/openid_connect/id_token'
Expand Down Expand Up @@ -65,26 +64,22 @@ def self.signing_key_normalized
end
end

if defined?(::Doorkeeper::GrantFlow)
Doorkeeper::GrantFlow.register(
:id_token,
response_type_matches: 'id_token',
response_type_strategy: Doorkeeper::OpenidConnect::IdToken,
)
Doorkeeper::GrantFlow.register(
:id_token,
response_type_matches: 'id_token',
response_mode_matches: %w[fragment form_post],
response_type_strategy: Doorkeeper::OpenidConnect::IdToken,
)

Doorkeeper::GrantFlow.register(
'id_token token',
response_type_matches: 'id_token token',
response_type_strategy: Doorkeeper::OpenidConnect::IdTokenToken,
)
Doorkeeper::GrantFlow.register(
'id_token token',
response_type_matches: 'id_token token',
response_mode_matches: %w[fragment form_post],
response_type_strategy: Doorkeeper::OpenidConnect::IdTokenToken,
)

Doorkeeper::GrantFlow.register_alias(
'implicit_oidc', as: ['implicit', 'id_token', 'id_token token']
)
else
# TODO: drop this and corresponding file when we will set minimal
# required Doorkeeper version to 5.5.
Doorkeeper::Config.prepend OpenidConnect::ResponseTypeConfig
end
Doorkeeper::GrantFlow.register_alias(
'implicit_oidc', as: ['implicit', 'id_token', 'id_token token']
)
end
end
17 changes: 0 additions & 17 deletions lib/doorkeeper/openid_connect/response_types_config.rb

This file was deleted.

35 changes: 34 additions & 1 deletion spec/controllers/discovery_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

'scopes_supported' => ['openid'],
'response_types_supported' => ['code', 'token', 'id_token', 'id_token token'],
'response_modes_supported' => %w[query fragment],
'response_modes_supported' => %w[query fragment form_post],
'grant_types_supported' => %w[authorization_code client_credentials implicit_oidc],

'token_endpoint_auth_methods_supported' => %w[client_secret_basic client_secret_post],
Expand Down Expand Up @@ -65,6 +65,39 @@
end
end

context 'when grant_flows is configed with only client_credentials' do
before { Doorkeeper.configure { grant_flows %w[client_credentials] } }

it 'return empty response_modes_supported' do
get :provider
data = JSON.parse(response.body)

expect(data['response_modes_supported']).to eq []
end
end

context 'when grant_flows is configed only implicit flow' do
before { Doorkeeper.configure { grant_flows %w[implicit_oidc] } }

it 'return fragment and form_post as response_modes_supported' do
get :provider
data = JSON.parse(response.body)

expect(data['response_modes_supported']).to eq %w[fragment form_post]
end
end

context 'when grant_flows is configed with authorization_code and implicit flow' do
before { Doorkeeper.configure { grant_flows %w[authorization_code implicit_oidc] } }

it 'return query, fragment and form_post as response_modes_supported' do
get :provider
data = JSON.parse(response.body)

expect(data['response_modes_supported']).to eq %w[query fragment form_post]
end
end

it 'uses the protocol option for generating URLs' do
Doorkeeper::OpenidConnect.configure do
protocol { :testing }
Expand Down
18 changes: 15 additions & 3 deletions spec/lib/oauth/id_token_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
:pre_auth,
client: application,
redirect_uri: 'http://tst.com/cb',
state: nil,
state: 'state',
scopes: Doorkeeper::OAuth::Scopes.from_string('public'),
error: nil,
authorizable?: true,
Expand All @@ -36,9 +36,21 @@
end
let(:id_token) { Doorkeeper::OpenidConnect::IdToken.new(token, pre_auth) }

describe '#body' do
it 'return body response for id_token' do
expect(subject.body).to eq({
expires_in: auth.token.expires_in_seconds,
state: pre_auth.state,
id_token: id_token.as_jws_token
})
end
end

describe '#redirect_uri' do
it 'includes id_token' do
expect(subject.redirect_uri).to include('id_token')
it 'includes expires_in, id_token and state' do
expect(subject.redirect_uri).to include("#{pre_auth.redirect_uri}#expires_in=#{auth.token.expires_in_seconds}&" \
"state=#{pre_auth.state}&" \
"id_token=#{id_token.as_jws_token}")
end

it 'does not include access_token' do
Expand Down
27 changes: 17 additions & 10 deletions spec/lib/oauth/id_token_token_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
:pre_auth,
client: application,
redirect_uri: 'http://tst.com/cb',
state: nil,
state: 'state',
scopes: Doorkeeper::OAuth::Scopes.from_string('public'),
error: nil,
authorizable?: true,
Expand All @@ -33,17 +33,24 @@
end
let(:id_token) { Doorkeeper::OpenidConnect::IdToken.new(token, pre_auth) }

describe '#redirect_uri' do
it 'includes id_token' do
expect(subject.redirect_uri).to include('id_token')
end

it 'includes access_token' do
expect(subject.redirect_uri).to include('access_token')
describe '#body' do
it 'return body response for id_token and access_token' do
expect(subject.body).to eq({
expires_in: auth.token.expires_in_seconds,
state: pre_auth.state,
id_token: id_token.as_jws_token,
access_token: auth.token.token,
token_type: auth.token.token_type
})
end
end

it 'includes token_type' do
expect(subject.redirect_uri).to include('token_type')
describe '#redirect_uri' do
it 'includes id_token, info of access_token and state' do
expect(subject.redirect_uri).to include("#{pre_auth.redirect_uri}#expires_in=#{auth.token.expires_in_seconds}&" \
"state=#{pre_auth.state}&" \
"id_token=#{id_token.as_jws_token}&" \
"access_token=#{auth.token.token}&token_type=#{auth.token.token_type}")
end
end
end