-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Nicholas Hance <nhance@reenhanced.com> Co-authored-by: stevenvegt <steven.vandervegt@nedap.com>
- Loading branch information
1 parent
8cbcc15
commit 4c3e07d
Showing
21 changed files
with
469 additions
and
12 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
module Doorkeeper | ||
module OAuth | ||
class IdTokenRequest | ||
attr_accessor :pre_auth, :auth, :resource_owner | ||
|
||
def initialize(pre_auth, resource_owner) | ||
@pre_auth = pre_auth | ||
@resource_owner = resource_owner | ||
end | ||
|
||
def authorize | ||
if pre_auth.authorizable? | ||
@auth = Authorization::Token.new(pre_auth, resource_owner) | ||
@auth.issue_token | ||
@response = response | ||
else | ||
@response = error_response | ||
end | ||
end | ||
|
||
def deny | ||
pre_auth.error = :access_denied | ||
error_response | ||
end | ||
|
||
private | ||
|
||
def response | ||
id_token = Doorkeeper::OpenidConnect::IdToken.new(auth.token, pre_auth.nonce) | ||
|
||
IdTokenResponse.new(pre_auth, auth, id_token) | ||
end | ||
|
||
def error_response | ||
ErrorResponse.from_request pre_auth, | ||
redirect_uri: pre_auth.redirect_uri, | ||
response_on_fragment: true | ||
end | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module Doorkeeper | ||
module OAuth | ||
class IdTokenResponse < BaseResponse | ||
include OAuth::Helpers | ||
|
||
attr_accessor :pre_auth, :auth, :id_token | ||
|
||
def initialize(pre_auth, auth, id_token) | ||
@pre_auth = pre_auth | ||
@auth = auth | ||
@id_token = id_token | ||
end | ||
|
||
def redirectable? | ||
true | ||
end | ||
|
||
def redirect_uri | ||
Authorization::URIBuilder.uri_with_fragment( | ||
pre_auth.redirect_uri, | ||
expires_in: auth.token.expires_in_seconds, | ||
state: pre_auth.state, | ||
id_token: id_token.as_jws_token | ||
) | ||
end | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module Doorkeeper | ||
module OAuth | ||
class IdTokenTokenRequest < IdTokenRequest | ||
private | ||
|
||
def response | ||
id_token_token = Doorkeeper::OpenidConnect::IdTokenToken.new(auth.token, pre_auth.nonce) | ||
|
||
IdTokenTokenResponse.new(pre_auth, auth, id_token_token) | ||
end | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module Doorkeeper | ||
module OAuth | ||
class IdTokenTokenResponse < IdTokenResponse | ||
def redirect_uri | ||
Authorization::URIBuilder.uri_with_fragment( | ||
pre_auth.redirect_uri, | ||
access_token: auth.token.token, | ||
token_type: auth.token.token_type, | ||
expires_in: auth.token.expires_in_seconds, | ||
state: pre_auth.state, | ||
id_token: id_token.as_jws_token | ||
) | ||
end | ||
end | ||
end | ||
end |
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
module Doorkeeper | ||
module OpenidConnect | ||
class IdTokenToken < IdToken | ||
def claims | ||
super.merge(at_hash: at_hash) | ||
end | ||
|
||
private | ||
|
||
# The at_hash is build according to the following standard: | ||
# | ||
# http://openid.net/specs/openid-connect-implicit-1_0.html#IDToken | ||
# | ||
# at_hash: | ||
# REQUIRED. Access Token hash value. If the ID Token is issued with an | ||
# access_token in an Implicit Flow, this is REQUIRED, which is the case | ||
# for this subset of OpenID Connect. Its value is the base64url encoding | ||
# of the left-most half of the hash of the octets of the ASCII | ||
# representation of the access_token value, where the hash algorithm | ||
# used is the hash algorithm used in the alg Header Parameter of the | ||
# ID Token's JOSE Header. For instance, if the alg is RS256, hash the | ||
# access_token value with SHA-256, then take the left-most 128 bits and | ||
# base64url-encode them. The at_hash value is a case-sensitive string. | ||
def at_hash | ||
sha256 = Digest::SHA256.new | ||
token = @access_token.token | ||
hashed_token = sha256.digest(token) | ||
first_half = hashed_token[0...hashed_token.length / 2] | ||
Base64.urlsafe_encode64(first_half).tr('=', '') | ||
end | ||
end | ||
end | ||
end |
22 changes: 22 additions & 0 deletions
22
lib/doorkeeper/openid_connect/oauth/authorization/token.rb
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module Doorkeeper | ||
module OpenidConnect | ||
module OAuth | ||
module Authorization | ||
module Code | ||
def issue_token | ||
super.tap do |access_grant| | ||
if pre_auth.nonce.present? | ||
::Doorkeeper::OpenidConnect::Request.create!( | ||
access_grant: access_grant, | ||
nonce: pre_auth.nonce | ||
) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
OAuth::Authorization::Code.send :prepend, OpenidConnect::OAuth::Authorization::Code | ||
end |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Doorkeeper | ||
module OpenidConnect | ||
module ResponseTypeConfig | ||
private def calculate_authorization_response_types | ||
types = super | ||
if grant_flows.include? 'implicit_oidc' | ||
types << 'token' | ||
types << 'id_token' | ||
types << 'id_token token' | ||
end | ||
types | ||
end | ||
end | ||
end | ||
|
||
Config.send :prepend, OpenidConnect::ResponseTypeConfig | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
require 'doorkeeper/request/strategy' | ||
|
||
module Doorkeeper | ||
module Request | ||
class IdToken < Strategy | ||
delegate :current_resource_owner, to: :server | ||
|
||
def pre_auth | ||
server.context.send(:pre_auth) | ||
end | ||
|
||
def request | ||
@request ||= OAuth::IdTokenRequest.new(pre_auth, current_resource_owner) | ||
end | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
require 'doorkeeper/request/strategy' | ||
|
||
module Doorkeeper | ||
module Request | ||
class IdTokenToken < Strategy | ||
delegate :current_resource_owner, to: :server | ||
|
||
def pre_auth | ||
server.context.send(:pre_auth) | ||
end | ||
|
||
def request | ||
@request ||= OAuth::IdTokenTokenRequest.new(pre_auth, current_resource_owner) | ||
end | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
require 'rails_helper' | ||
|
||
describe Doorkeeper::OpenidConnect::IdTokenToken do | ||
subject { described_class.new(access_token, nonce) } | ||
let(:access_token) { create :access_token, resource_owner_id: user.id } | ||
let(:user) { create :user } | ||
let(:nonce) { '123456' } | ||
|
||
before do | ||
allow(Time).to receive(:now) { Time.at 60 } | ||
end | ||
|
||
describe '#claims' do | ||
it 'returns all default claims' do | ||
# access token is from http://openid.net/specs/openid-connect-core-1_0.html | ||
# so we can test `at_hash` value | ||
access_token.update(token: 'jHkWEdUXMU1BwAsC4vtUsZwnNvTIxEl0z9K3vx5KF0Y') | ||
|
||
expect(subject.claims).to eq({ | ||
iss: 'dummy', | ||
sub: user.id.to_s, | ||
aud: access_token.application.uid, | ||
exp: 180, | ||
iat: 60, | ||
nonce: nonce, | ||
auth_time: 23, | ||
at_hash: '77QmUPtjPfzWtF2AnpK9RQ' | ||
}) | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
require 'rails_helper' | ||
|
||
describe Doorkeeper::OAuth::IdTokenTokenRequest do | ||
let(:application) do | ||
scopes = double(all: ['public']) | ||
double(:application, id: 9990, scopes: scopes) | ||
end | ||
|
||
let(:pre_auth) do | ||
double( | ||
:pre_auth, | ||
client: application, | ||
redirect_uri: 'http://tst.com/cb', | ||
state: nil, | ||
scopes: Doorkeeper::OAuth::Scopes.from_string('public'), | ||
error: nil, | ||
authorizable?: true, | ||
nonce: '12345' | ||
) | ||
end | ||
|
||
let(:owner) do | ||
double :owner, id: 7866 | ||
end | ||
|
||
subject do | ||
Doorkeeper::OAuth::IdTokenTokenRequest.new(pre_auth, owner) | ||
end | ||
|
||
it 'creates an access token' do | ||
expect do | ||
subject.authorize | ||
end.to change { Doorkeeper::AccessToken.count }.by(1) | ||
end | ||
|
||
it 'returns id_token token response' do | ||
expect(subject.authorize).to be_a(Doorkeeper::OAuth::IdTokenTokenResponse) | ||
end | ||
end |
Oops, something went wrong.