Skip to content
This repository has been archived by the owner on Aug 25, 2020. It is now read-only.

Commit

Permalink
assertion types can provide callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Covell committed Jul 16, 2012
1 parent df59bde commit ae53038
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
25 changes: 23 additions & 2 deletions lib/rack/oauth2/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,21 @@ def get_issuer(identifier)
# user = User.find_by_username(username)
# user if user && user.authenticated?(password)
# end
Options = Struct.new(:access_token_path, :authenticator, :authorization_types,
#
# Assertion handler is a hash of blocks keyed by assertion_type. Blocks receive
# three parameters: the client, the assertion, and the scope. If authenticated,
# it returns an identity. Otherwise it can return nil or false. For example:
# oauth.assertion_handler['facebook.com'] = lambda do |client, assertion, scope|
# facebook = URI.parse('https://graph.facebook.com/me?access_token=' + assertion)
# response = Net::HTTP.get_response(facebook)
#
# user_data = JSON.parse(response.body)
# user = User.from_facebook_data(user_data)
# end
# Assertion handlers are optional; if one is not present for a given assertion
# type, no error will result.
#
Options = Struct.new(:access_token_path, :authenticator, :assertion_handler, :authorization_types,
:authorize_path, :database, :host, :param_authentication, :path, :realm,
:expires_in,:logger, :collection_prefix)

Expand All @@ -204,6 +218,7 @@ def initialize(app, options = nil, &authenticator)
@app = app
@options = options || Server.options
@options.authenticator ||= authenticator
@options.assertion_handler ||= {}
@options.access_token_path ||= "/oauth/access_token"
@options.authorize_path ||= "/oauth/authorize"
@options.authorization_types ||= %w{code token}
Expand Down Expand Up @@ -422,10 +437,16 @@ def respond_with_access_token(request, logger)
assertion_type, assertion = request.POST.values_at("assertion_type", "assertion")
raise InvalidGrantError, "Missing assertion_type/assertion" unless assertion_type && assertion
# TODO: Add other supported assertion types (i.e. SAML) here
raise InvalidGrantError, "Unsupported assertion_type" if assertion_type != "urn:ietf:params:oauth:grant-type:jwt-bearer"
if assertion_type == "urn:ietf:params:oauth:grant-type:jwt-bearer"
identity = process_jwt_assertion(assertion)
access_token = AccessToken.get_token_for(identity, client, requested_scope, options.expires_in)
elsif options.assertion_handler[assertion_type]
args = [client, assertion, requested_scope]
identity = options.assertion_handler[assertion_type].call(*args)
raise InvalidGrantError, "Unknown assertion for #{assertion_type}" unless identity
access_token = AccessToken.get_token_for(identity, client, requested_scope, options.expires_in)
else
raise InvalidGrantError, "Unsupported assertion_type" if assertion_type != "urn:ietf:params:oauth:grant-type:jwt-bearer"
end
else
raise UnsupportedGrantType
Expand Down
35 changes: 35 additions & 0 deletions test/oauth/access_grant_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,41 @@ def request_with_assertion(assertion_type, assertion)
setup { request_with_assertion "urn:some:assertion:type", nil }
should_return_error :invalid_grant
end

context "assertion_type with callback" do
setup do
config.assertion_handler['special_assertion_type'] = lambda do |client, assertion, scope|
@client = client
@assertion = assertion
@scope = scope
if assertion == 'myassertion'
"Spiderman"
else
nil
end
end
request_with_assertion 'special_assertion_type', 'myassertion'
end

context "valid credentials" do
setup { request_with_assertion 'special_assertion_type', 'myassertion' }

should_respond_with_access_token "read write"
should "receive client" do
assert_equal client, @client
end
should "receieve assertion" do
assert_equal 'myassertion', @assertion
end
end

context "invalid credentials" do
setup { request_with_assertion 'special_assertion_type', 'dunno' }
should_return_error :invalid_grant
end

teardown { config.assertion_handler['special_assertion_type'] = nil }
end

context "unsupported assertion_type" do
setup { request_with_assertion "urn:some:assertion:type", "myassertion" }
Expand Down

0 comments on commit ae53038

Please sign in to comment.