Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add assertion strategy

  • Loading branch information...
commit 560fd789e70d23efa5fca3ab82b965d1594093e5 1 parent 08e7b4c
Dorren Chen dorren authored
6 README.md
View
@@ -61,9 +61,9 @@ instance will be returned as usual and on 400+ status code responses, the
Response instance will contain the OAuth2::Error instance.
## Authorization Grants
-Currently the Authorization Code, Resource Owner Password Credentials, and Client Credentials
+Currently the Authorization Code, Resource Owner Password Credentials, Client Credentials, and Assertion
authentication grant types have helper strategy classes that simplify client
-use. They are available via the #auth_code, #password, and #client_credentials methods respectively.
+use. They are available via the #auth_code, #password, #client_credentials, and #assertion methods respectively.
auth_url = client.auth_code.authorize_url(:redirect_uri => 'http://localhost:8080/oauth/callback')
token = client.auth_code.get_token('code_value', :redirect_uri => 'http://localhost:8080/oauth/callback')
@@ -72,6 +72,8 @@ use. They are available via the #auth_code, #password, and #client_credentials
token = client.client_credentials.get_token
+ token = client.assertion.get_token(assertion_params)
+
If you want to specify additional headers to be sent out with the
request, add a 'headers' hash under 'params':
1  lib/oauth2.rb
View
@@ -4,5 +4,6 @@
require 'oauth2/strategy/auth_code'
require 'oauth2/strategy/password'
require 'oauth2/strategy/client_credentials'
+require 'oauth2/strategy/assertion'
require 'oauth2/access_token'
require 'oauth2/response'
4 lib/oauth2/client.rb
View
@@ -153,5 +153,9 @@ def password
def client_credentials
@client_credentials ||= OAuth2::Strategy::ClientCredentials.new(self)
end
+
+ def assertion
+ @assertion ||= OAuth2::Strategy::Assertion.new(self)
+ end
end
end
75 lib/oauth2/strategy/assertion.rb
View
@@ -0,0 +1,75 @@
+require 'httpauth'
+require 'jwt'
+
+module OAuth2
+ module Strategy
+ # The Client Assertion Strategy
+ #
+ # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.3
+ #
+ # Sample usage:
+ # client = OAuth2::Client.new(client_id, client_secret,
+ # :site => 'http://localhost:8080')
+ #
+ # params = {:hmac_secret => "some secret",
+ # # or :private_key => "private key string",
+ # :iss => "http://localhost:3001",
+ # :prn => "me@here.com",
+ # :exp => Time.now.utc.to_i + 3600}
+ #
+ # access = client.assertion.get_token(params)
+ # access.token # actual access_token string
+ # access.get("/api/stuff") # making api calls with access token in header
+ #
+ class Assertion < Base
+ # Not used for this strategy
+ #
+ # @raise [NotImplementedError]
+ def authorize_url
+ raise NotImplementedError, "The authorization endpoint is not used in this strategy"
+ end
+
+ # Retrieve an access token given the specified client.
+ #
+ # @param [Hash] params assertion params
+ # pass either :hmac_secret or :private_key, but not both.
+ #
+ # params :hmac_secret, secret string.
+ # params :private_key, private key string.
+ #
+ # params :iss, issuer
+ # params :aud, audience, optional
+ # params :prn, principal, current user
+ # params :exp, expired at, in seconds, like Time.now.utc.to_i + 3600
+ #
+ # @param [Hash] opts options
+ def get_token(params={}, opts={})
+ hash = build_request(params)
+ @client.get_token(hash, opts.merge('refresh_token' => nil))
+ end
+
+ def build_request(params)
+ assertion = build_assertion(params)
+ {:grant_type => "assertion",
+ :assertion_type => "urn:ietf:params:oauth:grant-type:jwt-bearer",
+ :assertion => assertion,
+ :scope => params[:scope]
+ }.merge(client_params)
+ end
+
+ def build_assertion(params)
+ claims = {:iss => params[:iss],
+ :aud => params[:aud],
+ :prn => params[:prn],
+ :exp => params[:exp]
+ }
+ if params[:hmac_secret]
+ jwt_assertion = JWT.encode(claims, params[:hmac_secret], "HS256")
+ elsif params[:private_key]
+ jwt_assertion = JWT.encode(claims, params[:private_key], "RS256")
+ end
+ end
+ end
+ end
+end
+
1  oauth2.gemspec
View
@@ -6,6 +6,7 @@ Gem::Specification.new do |gem|
gem.add_dependency 'httpauth', '~> 0.1'
gem.add_dependency 'multi_json', '~> 1.0'
gem.add_dependency 'rack', '~> 1.4'
+ gem.add_dependency 'jwt', '~> 0.1.4'
gem.add_development_dependency 'addressable'
gem.add_development_dependency 'multi_xml'
gem.add_development_dependency 'rake'
57 spec/oauth2/strategy/assertion_spec.rb
View
@@ -0,0 +1,57 @@
+require 'helper'
+
+describe OAuth2::Strategy::Assertion do
+ let(:client) do
+ cli = OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com')
+ cli.connection.build do |b|
+ b.adapter :test do |stub|
+ stub.post('/oauth/token') do |env|
+ case @mode
+ when "formencoded"
+ [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, 'expires_in=600&access_token=salmon&refresh_token=trout']
+ when "json"
+ [200, {'Content-Type' => 'application/json'}, '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}']
+ end
+ end
+ end
+ end
+ cli
+ end
+
+ let(:params) { {:hmac_secret => 'foo'}}
+
+ subject {client.assertion}
+
+ describe "#authorize_url" do
+ it "should raise NotImplementedError" do
+ lambda {subject.authorize_url}.should raise_error(NotImplementedError)
+ end
+ end
+
+ %w(json formencoded).each do |mode|
+ describe "#get_token (#{mode})" do
+ before do
+ @mode = mode
+ @access = subject.get_token(params)
+ end
+
+ it 'returns AccessToken with same Client' do
+ @access.client.should == client
+ end
+
+ it 'returns AccessToken with #token' do
+ @access.token.should == 'salmon'
+ end
+
+ it 'returns AccessToken with #expires_in' do
+ @access.expires_in.should == 600
+ end
+
+ it 'returns AccessToken with #expires_at' do
+ @access.expires_at.should_not be_nil
+ end
+ end
+ end
+
+end
+
Please sign in to comment.
Something went wrong with that request. Please try again.