rack-oauth2-1.4.0/ 0000755 0000041 0000041 00000000000 12750322535 013670 5 ustar www-data www-data rack-oauth2-1.4.0/Rakefile 0000644 0000041 0000041 00000000620 12750322535 015333 0 ustar www-data www-data require 'bundler'
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
namespace :coverage do
desc "Open coverage report"
task :report do
require 'simplecov'
`open "#{File.join SimpleCov.coverage_path, 'index.html'}"`
end
end
task :spec do
Rake::Task[:'coverage:report'].invoke unless ENV['TRAVIS_RUBY_VERSION']
end
task default: :spec
rack-oauth2-1.4.0/Gemfile 0000644 0000041 0000041 00000000136 12750322535 015163 0 ustar www-data www-data source 'http://rubygems.org'
platforms :jruby do
gem 'jruby-openssl', '>= 0.7'
end
gemspec rack-oauth2-1.4.0/.rspec 0000644 0000041 0000041 00000000037 12750322535 015005 0 ustar www-data www-data --color
--format=documentation
rack-oauth2-1.4.0/spec/ 0000755 0000041 0000041 00000000000 12750322535 014622 5 ustar www-data www-data rack-oauth2-1.4.0/spec/mock_response/ 0000755 0000041 0000041 00000000000 12750322535 017471 5 ustar www-data www-data rack-oauth2-1.4.0/spec/mock_response/resources/ 0000755 0000041 0000041 00000000000 12750322535 021503 5 ustar www-data www-data rack-oauth2-1.4.0/spec/mock_response/resources/fake.txt 0000644 0000041 0000041 00000000004 12750322535 023144 0 ustar www-data www-data fake rack-oauth2-1.4.0/spec/mock_response/errors/ 0000755 0000041 0000041 00000000000 12750322535 021005 5 ustar www-data www-data rack-oauth2-1.4.0/spec/mock_response/errors/invalid_request.json 0000644 0000041 0000041 00000000112 12750322535 025070 0 ustar www-data www-data {
"error":"invalid_request",
"error_description":"error description"
} rack-oauth2-1.4.0/spec/mock_response/blank 0000644 0000041 0000041 00000000000 12750322535 020471 0 ustar www-data www-data rack-oauth2-1.4.0/spec/mock_response/tokens/ 0000755 0000041 0000041 00000000000 12750322535 020774 5 ustar www-data www-data rack-oauth2-1.4.0/spec/mock_response/tokens/legacy_without_expires_in.txt 0000644 0000041 0000041 00000000031 12750322535 027003 0 ustar www-data www-data access_token=access_token rack-oauth2-1.4.0/spec/mock_response/tokens/unknown.json 0000644 0000041 0000041 00000000165 12750322535 023370 0 ustar www-data www-data {
"access_token":"access_token",
"refresh_token":"refresh_token",
"token_type":"unknown",
"expires_in":3600
} rack-oauth2-1.4.0/spec/mock_response/tokens/bearer.json 0000644 0000041 0000041 00000000164 12750322535 023130 0 ustar www-data www-data {
"access_token":"access_token",
"refresh_token":"refresh_token",
"token_type":"bearer",
"expires_in":3600
} rack-oauth2-1.4.0/spec/mock_response/tokens/legacy.json 0000644 0000041 0000041 00000000133 12750322535 023130 0 ustar www-data www-data {
"access_token":"access_token",
"refresh_token":"refresh_token",
"expires_in":3600
} rack-oauth2-1.4.0/spec/mock_response/tokens/mac.json 0000644 0000041 0000041 00000000252 12750322535 022426 0 ustar www-data www-data {
"token_type":"mac",
"mac_algorithm":"hmac-sha-256",
"expires_in":3600,
"mac_key":"secret",
"refresh_token":"refresh_token",
"access_token":"access_token"
}
rack-oauth2-1.4.0/spec/mock_response/tokens/_Bearer.json 0000644 0000041 0000041 00000000164 12750322535 023227 0 ustar www-data www-data {
"access_token":"access_token",
"refresh_token":"refresh_token",
"token_type":"Bearer",
"expires_in":3600
} rack-oauth2-1.4.0/spec/mock_response/tokens/legacy.txt 0000644 0000041 0000041 00000000046 12750322535 023001 0 ustar www-data www-data access_token=access_token&expires=3600 rack-oauth2-1.4.0/spec/spec_helper.rb 0000644 0000041 0000041 00000000605 12750322535 017441 0 ustar www-data www-data require 'simplecov'
SimpleCov.start do
add_filter 'spec'
end
require 'rspec'
require 'rspec/its'
require 'rack/oauth2'
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = [:should, :expect]
end
end
require 'helpers/time'
require 'helpers/webmock_helper'
def simple_app
lambda do |env|
[ 200, {'Content-Type' => 'text/plain'}, ["HELLO"] ]
end
end
rack-oauth2-1.4.0/spec/helpers/ 0000755 0000041 0000041 00000000000 12750322535 016264 5 ustar www-data www-data rack-oauth2-1.4.0/spec/helpers/time.rb 0000644 0000041 0000041 00000000506 12750322535 017550 0 ustar www-data www-data class Time
class << self
module NowWithFixedTime
def now
if @fixed_time
@fixed_time.dup
else
super
end
end
end
prepend NowWithFixedTime
def fix(time = Time.now)
@fixed_time = time
yield
ensure
@fixed_time = nil
end
end
end
rack-oauth2-1.4.0/spec/helpers/webmock_helper.rb 0000644 0000041 0000041 00000001635 12750322535 021604 0 ustar www-data www-data require 'webmock/rspec'
module WebMockHelper
def mock_response(method, endpoint, response_file, options = {})
stub_request(method, endpoint).with(
request_for(method, options)
).to_return(
response_for(response_file, options)
)
end
private
def request_for(method, options = {})
request = {}
params = options.try(:[], :params) || {}
case method
when :post, :put, :delete
request[:body] = params
else
request[:query] = params
end
if options[:request_header]
request[:headers] = options[:request_header]
end
request
end
def response_for(response_file, options = {})
response = {}
response[:body] = File.new(File.join(File.dirname(__FILE__), '../mock_response', response_file))
if options[:status]
response[:status] = options[:status]
end
response
end
end
include WebMockHelper
WebMock.disable_net_connect! rack-oauth2-1.4.0/spec/rack/ 0000755 0000041 0000041 00000000000 12750322535 015542 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/ 0000755 0000041 0000041 00000000000 12750322535 016744 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/ 0000755 0000041 0000041 00000000000 12750322535 020252 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/authorize_spec.rb 0000644 0000041 0000041 00000015177 12750322535 023636 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Authorize do
let(:app) { Rack::OAuth2::Server::Authorize.new }
let(:request) { Rack::MockRequest.new app }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:bad_request) { Rack::OAuth2::Server::Authorize::BadRequest }
context 'when response_type is missing' do
it do
expect { request.get "/?client_id=client&redirect_uri=#{redirect_uri}" }.to raise_error bad_request
end
end
context 'when redirect_uri is missing' do
it do
expect { request.get "/?response_type=code&client_id=client" }.not_to raise_error
end
end
context 'when client_id is missing' do
it do
expect { request.get "/?response_type=code&redirect_uri=#{redirect_uri}" }.to raise_error bad_request
end
end
context 'when unknown response_type is given' do
it do
expect { request.get "/?response_type=unknown&client_id=client&redirect_uri=#{redirect_uri}" }.to raise_error bad_request
end
end
context 'when all required parameters are valid' do
[:code, :token].each do |request_type|
context "when response_type = :#{request_type}" do
subject { request.get "/?response_type=#{request_type}&client_id=client&redirect_uri=#{redirect_uri}" }
its(:status) { should == 200 }
end
end
end
describe Rack::OAuth2::Server::Authorize::Request do
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client&redirect_uri=#{redirect_uri}") }
let(:request) { Rack::OAuth2::Server::Authorize::Request.new env }
describe '#varified_redirect_uri' do
context 'when an Array of pre-registered URIs are given' do
context 'when given redirect_uri is valid against one of them' do
let :pre_registered do
[
redirect_uri,
'http://ja.client.example.com/callback',
'http://en.client.example.com/callback'
]
end
it 'should be valid' do
request.verify_redirect_uri!(pre_registered).should == redirect_uri
end
end
context 'otherwise' do
let :pre_registered do
[
'http://ja.client.example.com/callback',
'http://en.client.example.com/callback'
]
end
it do
expect do
request.verify_redirect_uri!(pre_registered)
end.to raise_error bad_request
end
end
end
context 'when exact mathed redirect_uri is given' do
let(:pre_registered) { redirect_uri }
it 'should be valid' do
request.verify_redirect_uri!(pre_registered).should == redirect_uri
end
end
context 'when partially mathed redirect_uri is given' do
let(:pre_registered) { 'http://client.example.com' }
context 'when partial matching allowed' do
it 'should be valid' do
request.verify_redirect_uri!(pre_registered, :allow_partial_match).should == redirect_uri
end
end
context 'otherwise' do
it do
expect do
request.verify_redirect_uri!(pre_registered)
end.to raise_error bad_request
end
end
end
context 'when invalid redirect_uri is given' do
let(:pre_registered) { 'http://client2.example.com' }
it do
expect do
request.verify_redirect_uri!(pre_registered)
end.to raise_error bad_request
end
end
context 'when redirect_uri is missing' do
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client") }
context 'when pre-registered redirect_uri is a String' do
let(:pre_registered) { redirect_uri }
it 'should use pre-registered redirect_uri' do
request.verify_redirect_uri!(pre_registered).should == pre_registered
end
end
context 'when pre-registered redirect_uri is an Array' do
context 'when only 1' do
let(:pre_registered) { [redirect_uri] }
context 'when partial match allowed' do
it do
expect do
request.verify_redirect_uri!(pre_registered, :allow_partial_match)
end.to raise_error bad_request
end
end
context 'otherwise' do
it 'should use pre-registered redirect_uri' do
request.verify_redirect_uri!(pre_registered).should == pre_registered.first
end
end
end
context 'when more than 2' do
let(:pre_registered) { [redirect_uri, 'http://client.example.com/callback2'] }
it do
expect do
request.verify_redirect_uri!(pre_registered)
end.to raise_error bad_request
end
end
end
end
end
end
describe 'extensibility' do
before do
require 'rack/oauth2/server/authorize/extension/code_and_token'
end
let(:env) do
Rack::MockRequest.env_for("/authorize?response_type=#{response_type}&client_id=client")
end
let(:request) { Rack::OAuth2::Server::Authorize::Request.new env }
its(:extensions) { should == [Rack::OAuth2::Server::Authorize::Extension::CodeAndToken] }
describe 'code token' do
let(:response_type) { 'code%20token' }
it do
app.send(
:response_type_for, request
).should == Rack::OAuth2::Server::Authorize::Extension::CodeAndToken
end
end
describe 'token code' do
let(:response_type) { 'token%20code' }
it do
app.send(
:response_type_for, request
).should == Rack::OAuth2::Server::Authorize::Extension::CodeAndToken
end
end
describe 'token code id_token' do
let(:response_type) { 'token%20code%20id_token' }
it do
expect do
app.send(:response_type_for, request)
end.to raise_error bad_request
end
end
describe 'id_token' do
before do
class Rack::OAuth2::Server::Authorize::Extension::IdToken < Rack::OAuth2::Server::Abstract::Handler
def self.response_type_for?(response_type)
response_type == 'id_token'
end
end
end
its(:extensions) do
should == [
Rack::OAuth2::Server::Authorize::Extension::CodeAndToken,
Rack::OAuth2::Server::Authorize::Extension::IdToken
]
end
let(:response_type) { 'id_token' }
it do
app.send(
:response_type_for, request
).should == Rack::OAuth2::Server::Authorize::Extension::IdToken
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/resource_spec.rb 0000644 0000041 0000041 00000001153 12750322535 023440 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Resource do
subject { Rack::OAuth2::Server::Resource.new(simple_app, 'realm') }
its(:realm) { should == 'realm' }
end
describe Rack::OAuth2::Server::Resource::Request do
let(:env) { Rack::MockRequest.env_for('/protected_resource') }
let(:request) { Rack::OAuth2::Server::Resource::Request.new(env) }
describe '#setup!' do
it do
expect { request.setup! }.to raise_error(RuntimeError, 'Define me!')
end
end
describe '#oauth2?' do
it do
expect { request.oauth2? }.to raise_error(RuntimeError, 'Define me!')
end
end
end rack-oauth2-1.4.0/spec/rack/oauth2/server/authorize/ 0000755 0000041 0000041 00000000000 12750322535 022264 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/authorize/error_spec.rb 0000644 0000041 0000041 00000007437 12750322535 024767 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Authorize::BadRequest do
let(:klass) { Rack::OAuth2::Server::Authorize::BadRequest }
let(:error) { klass.new(:invalid_request) }
let(:redirect_uri) { 'http://client.example.com/callback' }
subject { error }
it { should be_a Rack::OAuth2::Server::Abstract::BadRequest }
its(:protocol_params) do
should == {
error: :invalid_request,
error_description: nil,
error_uri: nil,
state: nil
}
end
describe '#finish' do
context 'when redirect_uri is given' do
before { error.redirect_uri = redirect_uri }
context 'when protocol_params_location = :query' do
before { error.protocol_params_location = :query }
it 'should redirect with error in query' do
state, header, response = error.finish
state.should == 302
header["Location"].should == "#{redirect_uri}?error=invalid_request"
end
end
context 'when protocol_params_location = :fragment' do
before { error.protocol_params_location = :fragment }
it 'should redirect with error in fragment' do
state, header, response = error.finish
state.should == 302
header["Location"].should == "#{redirect_uri}#error=invalid_request"
end
end
context 'otherwise' do
before { error.protocol_params_location = :other }
it 'should redirect without error' do
state, header, response = error.finish
state.should == 302
header["Location"].should == redirect_uri
end
end
end
context 'otherwise' do
it 'should raise itself' do
expect { error.finish }.to raise_error(klass) { |e|
e.should == error
}
end
end
end
end
describe Rack::OAuth2::Server::Authorize::ErrorMethods do
let(:klass) { Rack::OAuth2::Server::Authorize::BadRequest }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:default_description) { Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION }
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
let(:request) { Rack::OAuth2::Server::Authorize::Request.new env }
let(:request_for_code) { Rack::OAuth2::Server::Authorize::Code::Request.new env }
let(:request_for_token) { Rack::OAuth2::Server::Authorize::Token::Request.new env }
describe 'bad_request!' do
it do
expect { request.bad_request! }.to raise_error klass
end
context 'when response_type = :code' do
it 'should set protocol_params_location = :query' do
expect { request_for_code.bad_request! }.to raise_error(klass) { |e|
e.protocol_params_location.should == :query
}
end
end
context 'when response_type = :token' do
it 'should set protocol_params_location = :fragment' do
expect { request_for_token.bad_request! }.to raise_error(klass) { |e|
e.protocol_params_location.should == :fragment
}
end
end
end
Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION.keys.each do |error_code|
method = "#{error_code}!"
klass = case error_code
when :server_error
Rack::OAuth2::Server::Authorize::ServerError
when :temporarily_unavailable
Rack::OAuth2::Server::Authorize::TemporarilyUnavailable
else
Rack::OAuth2::Server::Authorize::BadRequest
end
describe method do
it "should raise #{klass} with error = :#{error_code}" do
klass =
expect { request.send method }.to raise_error(klass) { |error|
error.error.should == error_code
error.description.should == default_description[error_code]
}
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/authorize/extensions/ 0000755 0000041 0000041 00000000000 12750322535 024463 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/authorize/extensions/code_and_token_spec.rb 0000644 0000041 0000041 00000004312 12750322535 030756 0 ustar www-data www-data require 'spec_helper.rb'
require 'rack/oauth2/server/authorize/extension/code_and_token'
describe Rack::OAuth2::Server::Authorize::Extension::CodeAndToken do
let(:request) { Rack::MockRequest.new app }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:access_token) { 'access_token' }
let(:authorization_code) { 'authorization_code' }
let(:response) do
request.get("/?response_type=code%20token&client_id=client&redirect_uri=#{redirect_uri}")
end
context "when approved" do
subject { response }
let(:bearer_token) { Rack::OAuth2::AccessToken::Bearer.new(access_token: access_token) }
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
response.redirect_uri = redirect_uri
response.access_token = bearer_token
response.code = authorization_code
response.approve!
end
end
its(:status) { should == 302 }
its(:location) { should include "#{redirect_uri}#" }
its(:location) { should include "code=#{authorization_code}"}
its(:location) { should include "access_token=#{access_token}"}
its(:location) { should include 'token_type=bearer' }
context 'when refresh_token is given' do
let :bearer_token do
Rack::OAuth2::AccessToken::Bearer.new(
access_token: access_token,
refresh_token: 'refresh'
)
end
its(:location) { should include "#{redirect_uri}#" }
its(:location) { should include "code=#{authorization_code}"}
its(:location) { should include "access_token=#{access_token}"}
its(:location) { should include 'token_type=bearer' }
end
end
context 'when denied' do
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
request.verify_redirect_uri! redirect_uri
request.access_denied!
end
end
it 'should redirect with error in fragment' do
response.status.should == 302
error_message = {
error: :access_denied,
error_description: Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION[:access_denied]
}
response.location.should == "#{redirect_uri}##{error_message.to_query}"
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/authorize/token_spec.rb 0000644 0000041 0000041 00000004577 12750322535 024760 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Authorize::Token do
let(:request) { Rack::MockRequest.new app }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:access_token) { 'access_token' }
let(:response) { request.get("/?response_type=token&client_id=client&redirect_uri=#{redirect_uri}&state=state") }
context "when approved" do
subject { response }
let(:bearer_token) { Rack::OAuth2::AccessToken::Bearer.new(access_token: access_token) }
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
response.redirect_uri = redirect_uri
response.access_token = bearer_token
response.approve!
end
end
its(:status) { should == 302 }
its(:location) { should == "#{redirect_uri}#access_token=#{access_token}&state=state&token_type=bearer" }
context 'when refresh_token is given' do
let :bearer_token do
Rack::OAuth2::AccessToken::Bearer.new(
access_token: access_token,
refresh_token: 'refresh'
)
end
its(:location) { should == "#{redirect_uri}#access_token=#{access_token}&state=state&token_type=bearer" }
end
context 'when redirect_uri is missing' do
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
response.access_token = bearer_token
response.approve!
end
end
it do
expect { response }.to raise_error AttrRequired::AttrMissing
end
end
context 'when access_token is missing' do
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
response.redirect_uri = redirect_uri
response.approve!
end
end
it do
expect { response }.to raise_error AttrRequired::AttrMissing
end
end
end
context 'when denied' do
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
request.verify_redirect_uri! redirect_uri
request.access_denied!
end
end
it 'should redirect with error in fragment' do
response.status.should == 302
error_message = {
error: :access_denied,
error_description: Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION[:access_denied]
}
response.location.should == "#{redirect_uri}##{error_message.to_query}&state=state"
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/authorize/code_spec.rb 0000644 0000041 0000041 00000003624 12750322535 024542 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Authorize::Code do
let(:request) { Rack::MockRequest.new app }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:authorization_code) { 'authorization_code' }
let(:response) { request.get "/?response_type=code&client_id=client&redirect_uri=#{redirect_uri}&state=state" }
context 'when approved' do
subject { response }
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
response.redirect_uri = redirect_uri
response.code = authorization_code
response.approve!
end
end
its(:status) { should == 302 }
its(:location) { should == "#{redirect_uri}?code=#{authorization_code}&state=state" }
context 'when redirect_uri already includes query' do
let(:redirect_uri) { 'http://client.example.com/callback?k=v' }
its(:location) { should == "#{redirect_uri}&code=#{authorization_code}&state=state" }
end
context 'when redirect_uri is missing' do
let(:redirect_uri) { nil }
it do
expect { response }.to raise_error AttrRequired::AttrMissing
end
end
context 'when code is missing' do
let(:authorization_code) { nil }
it do
expect { response }.to raise_error AttrRequired::AttrMissing
end
end
end
context 'when denied' do
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
request.verify_redirect_uri! redirect_uri
request.access_denied!
end
end
it 'should redirect with error in query' do
response.status.should == 302
error_message = {
error: :access_denied,
error_description: Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION[:access_denied]
}
response.location.should == "#{redirect_uri}?#{error_message.to_query}&state=state"
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/ 0000755 0000041 0000041 00000000000 12750322535 022101 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/mac/ 0000755 0000041 0000041 00000000000 12750322535 022641 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/mac/error_spec.rb 0000644 0000041 0000041 00000003351 12750322535 025333 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Resource::MAC::Unauthorized do
let(:error) { Rack::OAuth2::Server::Resource::MAC::Unauthorized.new(:invalid_token) }
it { should be_a Rack::OAuth2::Server::Resource::Unauthorized }
describe '#scheme' do
subject { error }
its(:scheme) { should == :MAC }
end
describe '#finish' do
it 'should use MAC scheme' do
status, header, response = error.finish
header['WWW-Authenticate'].should =~ /^MAC /
end
end
end
describe Rack::OAuth2::Server::Resource::MAC::ErrorMethods do
let(:unauthorized) { Rack::OAuth2::Server::Resource::MAC::Unauthorized }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:default_description) { Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION }
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
let(:request) { Rack::OAuth2::Server::Resource::MAC::Request.new env }
describe 'unauthorized!' do
it do
expect { request.unauthorized! :invalid_client }.to raise_error unauthorized
end
end
Rack::OAuth2::Server::Resource::Bearer::ErrorMethods::DEFAULT_DESCRIPTION.keys.each do |error_code|
method = "#{error_code}!"
case error_code
when :invalid_request
# ignore
when :insufficient_scope
# ignore
else
describe method do
it "should raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized with error = :#{error_code}" do
expect { request.send method }.to raise_error(unauthorized) { |error|
error.error.should == error_code
error.description.should == default_description[error_code]
}
end
end
end
end
end rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/bearer/ 0000755 0000041 0000041 00000000000 12750322535 023341 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/bearer/error_spec.rb 0000644 0000041 0000041 00000003404 12750322535 026032 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Resource::Bearer::Unauthorized do
let(:error) { Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(:invalid_token) }
it { should be_a Rack::OAuth2::Server::Resource::Unauthorized }
describe '#scheme' do
subject { error }
its(:scheme) { should == :Bearer }
end
describe '#finish' do
it 'should use Bearer scheme' do
status, header, response = error.finish
header['WWW-Authenticate'].should include 'Bearer'
end
end
end
describe Rack::OAuth2::Server::Resource::Bearer::ErrorMethods do
let(:unauthorized) { Rack::OAuth2::Server::Resource::Bearer::Unauthorized }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:default_description) { Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION }
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
let(:request) { Rack::OAuth2::Server::Resource::Bearer::Request.new env }
describe 'unauthorized!' do
it do
expect { request.unauthorized! :invalid_client }.to raise_error unauthorized
end
end
Rack::OAuth2::Server::Resource::Bearer::ErrorMethods::DEFAULT_DESCRIPTION.keys.each do |error_code|
method = "#{error_code}!"
case error_code
when :invalid_request
# ignore
when :insufficient_scope
# ignore
else
describe method do
it "should raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized with error = :#{error_code}" do
expect { request.send method }.to raise_error(unauthorized) { |error|
error.error.should == error_code
error.description.should == default_description[error_code]
}
end
end
end
end
end rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/error_spec.rb 0000644 0000041 0000041 00000012055 12750322535 024574 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Resource::BadRequest do
let(:error) { Rack::OAuth2::Server::Resource::BadRequest.new(:invalid_request) }
it { should be_a Rack::OAuth2::Server::Abstract::BadRequest }
describe '#finish' do
it 'should respond in JSON' do
status, header, response = error.finish
status.should == 400
header['Content-Type'].should == 'application/json'
response.body.should == ['{"error":"invalid_request"}']
end
end
end
describe Rack::OAuth2::Server::Resource::Unauthorized do
let(:error) { Rack::OAuth2::Server::Resource::Unauthorized.new(:invalid_token) }
let(:realm) { Rack::OAuth2::Server::Resource::DEFAULT_REALM }
it { should be_a Rack::OAuth2::Server::Abstract::Unauthorized }
describe '#scheme' do
it do
expect { error.scheme }.to raise_error(RuntimeError, 'Define me!')
end
end
context 'when scheme is defined' do
let :error_with_scheme do
e = error
e.instance_eval do
def scheme
:Scheme
end
end
e
end
describe '#finish' do
it 'should respond in JSON' do
status, header, response = error_with_scheme.finish
status.should == 401
header['Content-Type'].should == 'application/json'
header['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\", error=\"invalid_token\""
response.body.should == ['{"error":"invalid_token"}']
end
context 'when error_code is not invalid_token' do
let(:error) { Rack::OAuth2::Server::Resource::Unauthorized.new(:something) }
it 'should have error_code in body but not in WWW-Authenticate header' do
status, header, response = error_with_scheme.finish
header['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
response.body.first.should include '"error":"something"'
end
end
context 'when realm is specified' do
let(:realm) { 'server.example.com' }
let(:error) { Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(:something, nil, realm: realm) }
it 'should use given realm' do
status, header, response = error_with_scheme.finish
header['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
response.body.first.should include '"error":"something"'
end
end
end
end
end
describe Rack::OAuth2::Server::Resource::Forbidden do
let(:error) { Rack::OAuth2::Server::Resource::Forbidden.new(:insufficient_scope) }
it { should be_a Rack::OAuth2::Server::Abstract::Forbidden }
describe '#finish' do
it 'should respond in JSON' do
status, header, response = error.finish
status.should == 403
header['Content-Type'].should == 'application/json'
response.body.should == ['{"error":"insufficient_scope"}']
end
end
context 'when scope option is given' do
let(:error) { Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(:insufficient_scope, 'Desc', scope: [:scope1, :scope2]) }
it 'should have blank WWW-Authenticate header' do
status, header, response = error.finish
response.body.first.should include '"scope":"scope1 scope2"'
end
end
end
describe Rack::OAuth2::Server::Resource::Bearer::ErrorMethods do
let(:bad_request) { Rack::OAuth2::Server::Resource::BadRequest }
let(:forbidden) { Rack::OAuth2::Server::Resource::Forbidden }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:default_description) { Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION }
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
let(:request) { Rack::OAuth2::Server::Resource::Request.new env }
describe 'bad_request!' do
it do
expect { request.bad_request! :invalid_request }.to raise_error bad_request
end
end
describe 'unauthorized!' do
it do
expect { request.unauthorized! :invalid_client }.to raise_error(RuntimeError, 'Define me!')
end
end
Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION.keys.each do |error_code|
method = "#{error_code}!"
case error_code
when :invalid_request
describe method do
it "should raise Rack::OAuth2::Server::Resource::BadRequest with error = :#{error_code}" do
expect { request.send method }.to raise_error(bad_request) { |error|
error.error.should == error_code
error.description.should == default_description[error_code]
}
end
end
when :insufficient_scope
describe method do
it "should raise Rack::OAuth2::Server::Resource::Forbidden with error = :#{error_code}" do
expect { request.send method }.to raise_error(forbidden) { |error|
error.error.should == error_code
error.description.should == default_description[error_code]
}
end
end
else
describe method do
it do
expect { request.send method }.to raise_error(RuntimeError, 'Define me!')
end
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/bearer_spec.rb 0000644 0000041 0000041 00000007636 12750322535 024714 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Resource::Bearer do
let(:app) do
Rack::OAuth2::Server::Resource::Bearer.new(simple_app) do |request|
case request.access_token
when 'valid_token'
bearer_token
when 'insufficient_scope_token'
request.insufficient_scope!
else
request.invalid_token!
end
end
end
let(:bearer_token) do
Rack::OAuth2::AccessToken::Bearer.new(access_token: 'valid_token')
end
let(:access_token) { env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN] }
let(:request) { app.call(env) }
subject { app.call(env) }
shared_examples_for :authenticated_bearer_request do
it 'should be authenticated' do
status, header, response = request
status.should == 200
access_token.should == bearer_token
end
end
shared_examples_for :unauthorized_bearer_request do
it 'should be unauthorized' do
status, header, response = request
status.should == 401
header['WWW-Authenticate'].should include 'Bearer'
access_token.should be_nil
end
end
shared_examples_for :bad_bearer_request do
it 'should be bad_request' do
status, header, response = request
status.should == 400
access_token.should be_nil
end
end
shared_examples_for :skipped_authentication_request do
it 'should skip OAuth 2.0 authentication' do
status, header, response = request
status.should == 200
access_token.should be_nil
end
end
context 'when no access token is given' do
let(:env) { Rack::MockRequest.env_for('/protected_resource') }
it_behaves_like :skipped_authentication_request
end
context 'when valid_token is given' do
context 'when token is in Authorization header' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'Bearer valid_token') }
it_behaves_like :authenticated_bearer_request
end
context 'when token is in params' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', params: {access_token: 'valid_token'}) }
it_behaves_like :authenticated_bearer_request
end
end
context 'when invalid authorization header is given' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => '') }
it_behaves_like :skipped_authentication_request
end
context 'when invalid_token is given' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'Bearer invalid_token') }
context 'when token is in Authorization header' do
it_behaves_like :unauthorized_bearer_request
end
context 'when token is in params' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', params: {access_token: 'invalid_token'}) }
it_behaves_like :unauthorized_bearer_request
end
describe 'realm' do
context 'when specified' do
let(:realm) { 'server.example.com' }
let(:app) do
Rack::OAuth2::Server::Resource::Bearer.new(simple_app, realm) do |request|
request.unauthorized!
end
end
it 'should use specified realm' do
status, header, response = request
header['WWW-Authenticate'].should include "Bearer realm=\"#{realm}\""
end
end
context 'otherwize' do
it 'should use default realm' do
status, header, response = request
header['WWW-Authenticate'].should include "Bearer realm=\"#{Rack::OAuth2::Server::Resource::Bearer::DEFAULT_REALM}\""
end
end
end
end
context 'when multiple access_token is given' do
context 'when token is in Authorization header and params' do
let(:env) do
Rack::MockRequest.env_for(
'/protected_resource',
'HTTP_AUTHORIZATION' => 'Bearer valid_token',
params: {access_token: 'valid_token'}
)
end
it_behaves_like :bad_bearer_request
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/resource/mac_spec.rb 0000644 0000041 0000041 00000010227 12750322535 024202 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Resource::MAC do
let(:app) do
Rack::OAuth2::Server::Resource::MAC.new(simple_app) do |request|
case request.access_token
when 'valid_token'
token = mac_token
token.verify!(request)
token
when 'insufficient_scope_token'
request.insufficient_scope!
else
request.invalid_token!
end
end
end
let(:mac_token) do
Rack::OAuth2::AccessToken::MAC.new(
access_token: 'valid_token',
mac_key: 'secret',
mac_algorithm: 'hmac-sha-256',
ts: 1305820230 # fix verification time
)
end
let(:access_token) { env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN] }
let(:request) { app.call(env) }
subject { app.call(env) }
shared_examples_for :non_mac_request do
it 'should skip OAuth 2.0 authentication' do
status, header, response = request
status.should == 200
access_token.should be_nil
end
end
shared_examples_for :authenticated_mac_request do
it 'should be authenticated' do
status, header, response = request
status.should == 200
access_token.should == mac_token
end
end
shared_examples_for :unauthorized_mac_request do
it 'should be unauthorized' do
status, header, response = request
status.should == 401
header['WWW-Authenticate'].should include 'MAC'
access_token.should be_nil
end
end
shared_examples_for :bad_mac_request do
it 'should be unauthorized' do
status, header, response = request
status.should == 400
access_token.should be_nil
end
end
context 'when no access token is given' do
let(:env) { Rack::MockRequest.env_for('/protected_resource') }
it 'should skip OAuth 2.0 authentication' do
status, header, response = request
status.should == 200
access_token.should be_nil
end
end
context 'when valid_token is given' do
context 'when other required params are missing' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token"') }
it_behaves_like :unauthorized_mac_request
end
context 'when other required params are invalid' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token", nonce="51e74de734c05613f37520872e68db5f", ts="1305820234", mac="invalid""') }
it_behaves_like :unauthorized_mac_request
end
context 'when all required params are valid' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token", nonce="51e74de734c05613f37520872e68db5f", ts="1305820234", mac="26JP6MMZyAHLHeMU8+m+NbVJgZbikp5SlT86/a62pwg="') }
it_behaves_like :authenticated_mac_request
end
context 'when all required params are valid and ts is expired' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token", nonce="51e74de734c05613f37520872e68db5f", ts="1305819234", mac="nuo4765MZrVL/qMsAtuTczhqZAE5y02ChaLCyOiVU68="') }
it_behaves_like :unauthorized_mac_request
end
end
context 'when invalid_token is given' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="invalid_token"') }
it_behaves_like :unauthorized_mac_request
describe 'realm' do
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="invalid_token"') }
context 'when specified' do
let(:realm) { 'server.example.com' }
let(:app) do
Rack::OAuth2::Server::Resource::MAC.new(simple_app, realm) do |request|
request.unauthorized!
end
end
it 'should use specified realm' do
status, header, response = request
header['WWW-Authenticate'].should include "MAC realm=\"#{realm}\""
end
end
context 'otherwize' do
it 'should use default realm' do
status, header, response = request
header['WWW-Authenticate'].should include "MAC realm=\"#{Rack::OAuth2::Server::Resource::DEFAULT_REALM}\""
end
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/abstract/ 0000755 0000041 0000041 00000000000 12750322535 022055 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/abstract/error_spec.rb 0000644 0000041 0000041 00000003306 12750322535 024547 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Abstract::Error do
context 'when full attributes are given' do
subject do
Rack::OAuth2::Server::Abstract::Error.new 400, :invalid_request, 'Missing some required params', uri: 'http://server.example.com/error'
end
its(:status) { should == 400 }
its(:error) { should == :invalid_request }
its(:description) { should == 'Missing some required params' }
its(:uri) { should == 'http://server.example.com/error' }
its(:protocol_params) do
should == {
error: :invalid_request,
error_description: 'Missing some required params',
error_uri: 'http://server.example.com/error'
}
end
end
context 'when optional attributes are not given' do
subject do
Rack::OAuth2::Server::Abstract::Error.new 400, :invalid_request
end
its(:status) { should == 400 }
its(:error) { should == :invalid_request }
its(:description) { should be_nil }
its(:uri) { should be_nil }
its(:protocol_params) do
should == {
error: :invalid_request,
error_description: nil,
error_uri: nil
}
end
end
end
describe Rack::OAuth2::Server::Abstract::BadRequest do
its(:status) { should == 400 }
end
describe Rack::OAuth2::Server::Abstract::Unauthorized do
its(:status) { should == 401 }
end
describe Rack::OAuth2::Server::Abstract::Forbidden do
its(:status) { should == 403 }
end
describe Rack::OAuth2::Server::Abstract::ServerError do
its(:status) { should == 500 }
end
describe Rack::OAuth2::Server::Abstract::TemporarilyUnavailable do
its(:status) { should == 503 }
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/token/ 0000755 0000041 0000041 00000000000 12750322535 021372 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/server/token/client_credentials_spec.rb 0000644 0000041 0000041 00000001346 12750322535 026570 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Token::ClientCredentials do
let(:request) { Rack::MockRequest.new app }
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:params) do
{
grant_type: 'client_credentials',
client_id: 'client_id',
client_secret: 'client_secret'
}
end
subject { request.post('/', params: params) }
its(:status) { should == 200 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"access_token":"access_token"' }
its(:body) { should include '"token_type":"bearer"' }
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/token/authorization_code_spec.rb 0000644 0000041 0000041 00000002503 12750322535 026623 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Token::AuthorizationCode do
let(:request) { Rack::MockRequest.new app }
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:params) do
{
grant_type: 'authorization_code',
client_id: 'client_id',
code: 'authorization_code',
redirect_uri: 'http://client.example.com/callback'
}
end
let(:response) { request.post('/', params: params) }
subject { response }
its(:status) { should == 200 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"access_token":"access_token"' }
its(:body) { should include '"token_type":"bearer"' }
it 'should prevent to be cached' do
response.header['Cache-Control'].should == 'no-store'
response.header['Pragma'].should == 'no-cache'
end
[:code].each do |required|
context "when #{required} is missing" do
before do
params.delete_if do |key, value|
key == required
end
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/token/refresh_token_spec.rb 0000644 0000041 0000041 00000002034 12750322535 025566 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Token::RefreshToken do
let(:request) { Rack::MockRequest.new app }
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:params) do
{
grant_type: "refresh_token",
client_id: "client_id",
refresh_token: "refresh_token"
}
end
subject { request.post('/', params: params) }
its(:status) { should == 200 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"access_token":"access_token"' }
its(:body) { should include '"token_type":"bearer"' }
context 'when refresh_token is missing' do
before do
params.delete_if do |key, value|
key == :refresh_token
end
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/token/error_spec.rb 0000644 0000041 0000041 00000005322 12750322535 024064 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Token::BadRequest do
let(:error) { Rack::OAuth2::Server::Token::BadRequest.new(:invalid_request) }
it { should be_a Rack::OAuth2::Server::Abstract::BadRequest }
describe '#finish' do
it 'should respond in JSON' do
status, header, response = error.finish
status.should == 400
header['Content-Type'].should == 'application/json'
response.body.should == ['{"error":"invalid_request"}']
end
end
end
describe Rack::OAuth2::Server::Token::Unauthorized do
let(:error) { Rack::OAuth2::Server::Token::Unauthorized.new(:invalid_request) }
it { should be_a Rack::OAuth2::Server::Abstract::Unauthorized }
describe '#finish' do
it 'should respond in JSON' do
status, header, response = error.finish
status.should == 401
header['Content-Type'].should == 'application/json'
header['WWW-Authenticate'].should == 'Basic realm="OAuth2 Token Endpoint"'
response.body.should == ['{"error":"invalid_request"}']
end
end
end
describe Rack::OAuth2::Server::Token::ErrorMethods do
let(:bad_request) { Rack::OAuth2::Server::Token::BadRequest }
let(:unauthorized) { Rack::OAuth2::Server::Token::Unauthorized }
let(:redirect_uri) { 'http://client.example.com/callback' }
let(:default_description) { Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION }
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
let(:request) { Rack::OAuth2::Server::Token::Request.new env }
describe 'bad_request!' do
it do
expect { request.bad_request! :invalid_request }.to raise_error bad_request
end
end
describe 'unauthorized!' do
it do
expect { request.unauthorized! :invalid_client }.to raise_error unauthorized
end
end
Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION.keys.each do |error_code|
method = "#{error_code}!"
case error_code
when :invalid_client
describe method do
it "should raise Rack::OAuth2::Server::Token::Unauthorized with error = :#{error_code}" do
expect { request.send method }.to raise_error(unauthorized) { |error|
error.error.should == error_code
error.description.should == default_description[error_code]
}
end
end
else
describe method do
it "should raise Rack::OAuth2::Server::Token::BadRequest with error = :#{error_code}" do
expect { request.send method }.to raise_error(bad_request) { |error|
error.error.should == error_code
error.description.should == default_description[error_code]
}
end
end
end
end
end rack-oauth2-1.4.0/spec/rack/oauth2/server/token/saml2_bearer_spec.rb 0000644 0000041 0000041 00000002060 12750322535 025265 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Token::SAML2Bearer do
let(:request) { Rack::MockRequest.new app }
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:params) do
{
grant_type: 'urn:ietf:params:oauth:grant-type:saml2-bearer',
client_id: 'client_id',
assertion: '...'
}
end
subject { request.post('/', params: params) }
its(:status) { should == 200 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"access_token":"access_token"' }
its(:body) { should include '"token_type":"bearer"' }
context 'when assertion is missing' do
before do
params.delete_if do |key, value|
key == :assertion
end
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/token/jwt_bearer_spec.rb 0000644 0000041 0000041 00000002066 12750322535 025061 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Token::JWTBearer do
let(:request) { Rack::MockRequest.new app }
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:params) do
{
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
client_id: 'client_id',
assertion: 'header.payload.signature'
}
end
subject { request.post('/', params: params) }
its(:status) { should == 200 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"access_token":"access_token"' }
its(:body) { should include '"token_type":"bearer"' }
context 'when assertion is missing' do
before do
params.delete_if do |key, value|
key == :assertion
end
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/token/password_spec.rb 0000644 0000041 0000041 00000002134 12750322535 024573 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Server::Token::Password do
let(:request) { Rack::MockRequest.new app }
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:params) do
{
grant_type: 'password',
client_id: 'client_id',
username: 'nov',
password: 'secret'
}
end
subject { request.post('/', params: params) }
its(:status) { should == 200 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"access_token":"access_token"' }
its(:body) { should include '"token_type":"bearer"' }
[:username, :password].each do |required|
context "when #{required} is missing" do
before do
params.delete_if do |key, value|
key == required
end
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/server/token_spec.rb 0000644 0000041 0000041 00000007405 12750322535 022737 0 ustar www-data www-data require 'spec_helper.rb'
require 'base64'
describe Rack::OAuth2::Server::Token do
let(:request) { Rack::MockRequest.new app }
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:params) do
{
grant_type: 'authorization_code',
client_id: 'client_id',
code: 'authorization_code',
redirect_uri: 'http://client.example.com/callback'
}
end
subject { request.post('/token', params: params) }
context 'when multiple client credentials are given' do
context 'when different credentials are given' do
let(:env) do
Rack::MockRequest.env_for(
'/token',
'HTTP_AUTHORIZATION' => "Basic #{Base64.encode64('client_id2:client_secret')}",
params: params
)
end
it 'should fail with unsupported_grant_type' do
status, header, response = app.call(env)
status.should == 400
response.body.first.should include '"error":"invalid_request"'
end
end
context 'when same credentials are given' do
let(:env) do
Rack::MockRequest.env_for(
'/token',
'HTTP_AUTHORIZATION' => "Basic #{Base64.encode64('client_id:client_secret')}",
params: params
)
end
it 'should ignore duplicates' do
status, header, response = app.call(env)
status.should == 200
end
end
end
context 'when unsupported grant_type is given' do
before do
params.merge!(grant_type: 'unknown')
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"unsupported_grant_type"' }
end
[:client_id, :grant_type].each do |required|
context "when #{required} is missing" do
before do
params.delete_if do |key, value|
key == required
end
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
end
Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION.each do |error, default_message|
status = if error == :invalid_client
401
else
400
end
context "when #{error}" do
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
request.send "#{error}!"
end
end
its(:status) { should == status }
its(:content_type) { should == 'application/json' }
its(:body) { should include "\"error\":\"#{error}\"" }
its(:body) { should include "\"error_description\":\"#{default_message}\"" }
end
end
context 'when responding' do
context 'when access_token is missing' do
let(:app) do
Rack::OAuth2::Server::Token.new
end
it do
expect { request.post('/', params: params) }.to raise_error AttrRequired::AttrMissing
end
end
end
describe 'extensibility' do
before do
require 'rack/oauth2/server/token/extension/example'
end
subject { app }
let(:env) do
Rack::MockRequest.env_for(
'/token',
params: params
)
end
let(:request) { Rack::OAuth2::Server::Token::Request.new env }
its(:extensions) { should == [Rack::OAuth2::Server::Token::Extension::Example] }
describe 'JWT assertion' do
let(:params) do
{
grant_type: 'urn:ietf:params:oauth:grant-type:example',
assertion: 'header.payload.signature'
}
end
it do
app.send(
:grant_type_for, request
).should == Rack::OAuth2::Server::Token::Extension::Example
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token/ 0000755 0000041 0000041 00000000000 12750322535 021405 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/access_token/mac/ 0000755 0000041 0000041 00000000000 12750322535 022145 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/access_token/mac/sha256_hex_verifier_spec.rb 0000644 0000041 0000041 00000001504 12750322535 027253 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier do
# From the example of webtopay wallet API spec
# ref) https://www.webtopay.com/wallet/#authentication
context 'when example from webtopay wallet API' do
subject do
Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier.new(
algorithm: 'hmac-sha-256',
raw_body: 'grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=http%3A%2F%2Flocalhost%2Fabc'
)
end
its(:calculate) { should == '21fb73c40b589622d0c78e9cd8900f89d9472aa724d0e5c3eca9ac1cd9d2a6d5' }
end
context 'when raw_body is empty' do
subject do
Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier.new(
algorithm: 'hmac-sha-256',
raw_body: ''
)
end
its(:calculate) { should be_nil }
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token/mac/verifier_spec.rb 0000644 0000041 0000041 00000001310 12750322535 025312 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken::MAC::Verifier do
let(:verifier) { Rack::OAuth2::AccessToken::MAC::Verifier.new(algorithm: algorithm) }
subject { verifier }
context 'when "hmac-sha-1" is specified' do
let(:algorithm) { 'hmac-sha-1' }
its(:hash_generator) { should be_instance_of OpenSSL::Digest::SHA1 }
end
context 'when "hmac-sha-256" is specified' do
let(:algorithm) { 'hmac-sha-256' }
its(:hash_generator) { should be_instance_of OpenSSL::Digest::SHA256 }
end
context 'otherwise' do
let(:algorithm) { 'invalid' }
it do
expect { verifier.send(:hash_generator) }.to raise_error(StandardError, 'Unsupported Algorithm')
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token/mac/signature_spec.rb 0000644 0000041 0000041 00000003542 12750322535 025511 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken::MAC::Signature do
# From the example of Webtopay wallet API
# ref) https://www.webtopay.com/wallet/
context 'when ext is not given' do
subject do
Rack::OAuth2::AccessToken::MAC::Signature.new(
secret: 'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU',
algorithm: 'hmac-sha-256',
nonce: 'dj83hs9s',
ts: 1336363200,
method: 'GET',
request_uri: '/wallet/rest/api/v1/payment/123',
host: 'www.webtopay.com',
port: 443
)
end
its(:calculate) { should == 'OZE9fTk2qiRtL1jb01L8lRxC66PTiAGhMDEmboeVeLs=' }
end
# From the example of MAC spec section 1.1
# ref) http://tools.ietf.org/pdf/draft-ietf-oauth-v2-http-mac-01.pdf
context 'when ext is not given' do
subject do
Rack::OAuth2::AccessToken::MAC::Signature.new(
secret: '489dks293j39',
algorithm: 'hmac-sha-1',
nonce: 'dj83hs9s',
ts: 1336363200,
method: 'GET',
request_uri: '/resource/1?b=1&a=2',
host: 'example.com',
port: 80
)
end
its(:calculate) { should == '6T3zZzy2Emppni6bzL7kdRxUWL4=' }
end
# From the example of MAC spec section 3.2
# ref) http://tools.ietf.org/pdf/draft-ietf-oauth-v2-http-mac-01.pdf
context 'otherwise' do
subject do
Rack::OAuth2::AccessToken::MAC::Signature.new(
secret: '489dks293j39',
algorithm: 'hmac-sha-1',
nonce: '7d8f3e4a',
ts: 264095,
method: 'POST',
request_uri: '/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b&c2&a3=2+q',
host: 'example.com',
port: 80,
ext: 'a,b,c'
)
end
its(:calculate) { should == '+txL5oOFHGYjrfdNYH5VEzROaBY=' }
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token/legacy_spec.rb 0000644 0000041 0000041 00000001255 12750322535 024213 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken::Legacy do
let :token do
Rack::OAuth2::AccessToken::Legacy.new(
access_token: 'access_token'
)
end
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {hello: "world"}, {}) }
describe '#to_s' do
subject { token }
its(:to_s) { should == token.access_token }
end
describe '.authenticate' do
it 'should set Authorization header' do
expect(request.header).to receive(:[]=).with('Authorization', 'OAuth access_token')
token.authenticate(request)
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token/bearer_spec.rb 0000644 0000041 0000041 00000001113 12750322535 024200 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken::Bearer do
let :token do
Rack::OAuth2::AccessToken::Bearer.new(
access_token: 'access_token'
)
end
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {hello: "world"}, {}) }
describe '.authenticate' do
it 'should set Authorization header' do
expect(request.header).to receive(:[]=).with('Authorization', 'Bearer access_token')
token.authenticate(request)
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token/mac_spec.rb 0000644 0000041 0000041 00000011016 12750322535 023503 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken::MAC do
let(:ts) { 1305820234 }
let :token do
Rack::OAuth2::AccessToken::MAC.new(
access_token: 'access_token',
mac_key: 'secret',
mac_algorithm: 'hmac-sha-256',
ts: ts
)
end
let :token_with_ext_verifier do
Rack::OAuth2::AccessToken::MAC.new(
access_token: 'access_token',
mac_key: 'secret',
mac_algorithm: 'hmac-sha-256',
ts: ts,
ext_verifier: Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier
)
end
let(:nonce) { '1000:51e74de734c05613f37520872e68db5f' }
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
subject { token }
its(:mac_key) { should == 'secret' }
its(:mac_algorithm) { should == 'hmac-sha-256' }
its(:token_response) do
should == {
access_token: 'access_token',
refresh_token: nil,
token_type: :mac,
expires_in: nil,
scope: '',
mac_key: 'secret',
mac_algorithm: 'hmac-sha-256'
}
end
its(:generate_nonce) { should be_a String }
describe 'verify!' do
let(:request) { Rack::OAuth2::Server::Resource::MAC::Request.new(env) }
context 'when no ext_verifier is given' do
let(:env) do
Rack::MockRequest.env_for(
'/protected_resources',
'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="#{nonce}", ts="#{ts}" mac="#{signature}"}
)
end
context 'when signature is valid' do
let(:signature) { 'BgooS/voPOZWLwoVfx4+zbC3xAVKW3jtjhKYOfIGZOA=' }
it do
token.verify!(request.setup!).should == :verified
end
end
context 'otherwise' do
let(:signature) { 'invalid' }
it do
expect { token.verify!(request.setup!) }.to raise_error(
Rack::OAuth2::Server::Resource::MAC::Unauthorized,
'invalid_token :: Signature Invalid'
)
end
end
end
context 'when ext_verifier is given' do
let(:env) do
Rack::MockRequest.env_for(
'/protected_resources',
method: :POST,
params: {
key1: 'value1'
},
'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="#{nonce}", ts="#{ts}", mac="#{signature}", ext="#{ext}"}
)
end
let(:signature) { 'invalid' }
context 'when ext is invalid' do
let(:ext) { 'invalid' }
it do
expect { token_with_ext_verifier.verify!(request.setup!) }.to raise_error(
Rack::OAuth2::Server::Resource::MAC::Unauthorized,
'invalid_token :: Sha256HexVerifier Invalid'
)
end
end
context 'when ext is valid' do
let(:ext) { '4cfcd46c59f54b5ea6a5f9b05c28b52fef2864747194b5fdfc3d59c0057bf35a' }
context 'when signature is valid' do
let(:signature) { 'dZYR54n+Lym5qCRRmDqmRZ71rG+bkjSWmqrOv8OjYHk=' }
it do
Time.fix(Time.at(1302361200)) do
token_with_ext_verifier.verify!(request.setup!).should == :verified
end
end
end
context 'otherwise' do
it do
expect { token.verify!(request.setup!) }.to raise_error(
Rack::OAuth2::Server::Resource::MAC::Unauthorized,
'invalid_token :: Signature Invalid'
)
end
end
end
end
end
describe '.authenticate' do
let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {hello: "world"}, {}) }
context 'when no ext_verifier is given' do
let(:signature) { 'pOBaL6HRawe4tUPmcU4vJEj1f2GJqrbQOlCcdAYgI/s=' }
it 'should set Authorization header' do
expect(token).to receive(:generate_nonce).and_return(nonce)
expect(request.header).to receive(:[]=).with('Authorization', "MAC id=\"access_token\", nonce=\"#{nonce}\", ts=\"#{ts.to_i}\", mac=\"#{signature}\"")
token.authenticate(request)
end
end
context 'when ext_verifier is given' do
let(:signature) { 'vgU0fj6rSpwUCAoCOrXlu8pZBR8a5Q5xIVlB4MCvJeM=' }
let(:ext) { '3d011e09502a84552a0f8ae112d024cc2c115597e3a577d5f49007902c221dc5' }
it 'should set Authorization header with ext_verifier' do
expect(token_with_ext_verifier).to receive(:generate_nonce).and_return(nonce)
expect(request.header).to receive(:[]=).with('Authorization', "MAC id=\"access_token\", nonce=\"#{nonce}\", ts=\"#{ts.to_i}\", mac=\"#{signature}\", ext=\"#{ext}\"")
token_with_ext_verifier.authenticate(request)
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token/authenticator_spec.rb 0000644 0000041 0000041 00000002252 12750322535 025617 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken::Authenticator do
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
let(:request) { HTTP::Message.new_request(:get, URI.parse(resource_endpoint)) }
let(:authenticator) { Rack::OAuth2::AccessToken::Authenticator.new(token) }
shared_examples_for :authenticator do
it 'should let the token authenticate the request' do
expect(token).to receive(:authenticate).with(request)
authenticator.filter_request(request)
end
end
context 'when Legacy token is given' do
let(:token) do
Rack::OAuth2::AccessToken::Legacy.new(
access_token: 'access_token'
)
end
it_behaves_like :authenticator
end
context 'when Bearer token is given' do
let(:token) do
Rack::OAuth2::AccessToken::Bearer.new(
access_token: 'access_token'
)
end
it_behaves_like :authenticator
end
context 'when MAC token is given' do
let(:token) do
Rack::OAuth2::AccessToken::MAC.new(
access_token: 'access_token',
mac_key: 'secret',
mac_algorithm: 'hmac-sha-256'
)
end
it_behaves_like :authenticator
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client/ 0000755 0000041 0000041 00000000000 12750322535 020222 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/client/grant/ 0000755 0000041 0000041 00000000000 12750322535 021335 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/client/grant/client_credentials_spec.rb 0000644 0000041 0000041 00000000242 12750322535 026525 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client::Grant::ClientCredentials do
its(:as_json) do
should == {grant_type: :client_credentials}
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client/grant/authorization_code_spec.rb 0000644 0000041 0000041 00000001775 12750322535 026600 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client::Grant::AuthorizationCode do
let(:redirect_uri) { 'https://client.example.com/callback' }
let(:grant) { Rack::OAuth2::Client::Grant::AuthorizationCode }
context 'when code is given' do
let :attributes do
{code: 'code'}
end
context 'when redirect_uri is given' do
let :attributes do
{code: 'code', redirect_uri: redirect_uri}
end
subject { grant.new attributes }
its(:redirect_uri) { should == redirect_uri }
its(:as_json) do
should == {grant_type: :authorization_code, code: 'code', redirect_uri: redirect_uri}
end
end
context 'otherwise' do
subject { grant.new attributes }
its(:redirect_uri) { should be_nil }
its(:as_json) do
should == {grant_type: :authorization_code, code: 'code', redirect_uri: nil}
end
end
end
context 'otherwise' do
it do
expect { grant.new }.to raise_error AttrRequired::AttrMissing
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client/grant/refresh_token_spec.rb 0000644 0000041 0000041 00000001015 12750322535 025527 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client::Grant::RefreshToken do
let(:grant) { Rack::OAuth2::Client::Grant::RefreshToken }
context 'when refresh_token is given' do
let :attributes do
{refresh_token: 'refresh_token'}
end
subject { grant.new attributes }
its(:as_json) do
should == {grant_type: :refresh_token, refresh_token: 'refresh_token'}
end
end
context 'otherwise' do
it do
expect { grant.new }.to raise_error AttrRequired::AttrMissing
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client/grant/saml2_bearer_spec.rb 0000644 0000041 0000041 00000001046 12750322535 025233 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client::Grant::SAML2Bearer do
let(:grant) { Rack::OAuth2::Client::Grant::SAML2Bearer }
context 'when JWT assertion is given' do
let :attributes do
{assertion: '...'}
end
subject { grant.new attributes }
its(:as_json) do
should == {grant_type: 'urn:ietf:params:oauth:grant-type:saml2-bearer', assertion: '...'}
end
end
context 'otherwise' do
it do
expect { grant.new }.to raise_error AttrRequired::AttrMissing
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client/grant/jwt_bearer_spec.rb 0000644 0000041 0000041 00000001064 12750322535 025021 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client::Grant::JWTBearer do
let(:grant) { Rack::OAuth2::Client::Grant::JWTBearer }
context 'when JWT assertion is given' do
let :attributes do
{assertion: 'header.payload.signature'}
end
subject { grant.new attributes }
its(:as_json) do
should == {grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: 'header.payload.signature'}
end
end
context 'otherwise' do
it do
expect { grant.new }.to raise_error AttrRequired::AttrMissing
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client/grant/password_spec.rb 0000644 0000041 0000041 00000001431 12750322535 024535 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client::Grant::Password do
let(:grant) { Rack::OAuth2::Client::Grant::Password }
context 'when username is given' do
let :attributes do
{username: 'username'}
end
context 'when password is given' do
let :attributes do
{username: 'username', password: 'password'}
end
subject { grant.new attributes }
its(:as_json) do
should == {grant_type: :password, username: 'username', password: 'password'}
end
end
context 'otherwise' do
it do
expect { grant.new attributes }.to raise_error AttrRequired::AttrMissing
end
end
end
context 'otherwise' do
it do
expect { grant.new }.to raise_error AttrRequired::AttrMissing
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client/error_spec.rb 0000644 0000041 0000041 00000000705 12750322535 022714 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client::Error do
let :error do
{
error: :invalid_request,
error_description: 'Include invalid parameters',
error_uri: 'http://server.example.com/error/invalid_request'
}
end
subject do
Rack::OAuth2::Client::Error.new 400, error
end
its(:status) { should == 400 }
its(:message) { should == error[:error_description] }
its(:response) { should == error }
end
rack-oauth2-1.4.0/spec/rack/oauth2/debugger/ 0000755 0000041 0000041 00000000000 12750322535 020530 5 ustar www-data www-data rack-oauth2-1.4.0/spec/rack/oauth2/debugger/request_filter_spec.rb 0000644 0000041 0000041 00000002071 12750322535 025124 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::Debugger::RequestFilter do
let(:resource_endpoint) { 'https://example.com/resources' }
let(:request) { HTTP::Message.new_request(:get, URI.parse(resource_endpoint)) }
let(:response) { HTTP::Message.new_response(MultiJson.dump({hello: 'world'})) }
let(:request_filter) { Rack::OAuth2::Debugger::RequestFilter.new }
describe '#filter_request' do
it 'should log request' do
[
"======= [Rack::OAuth2] HTTP REQUEST STARTED =======",
request.dump
].each do |output|
expect(Rack::OAuth2.logger).to receive(:info).with output
end
request_filter.filter_request(request)
end
end
describe '#filter_response' do
it 'should log response' do
[
"--------------------------------------------------",
response.dump,
"======= [Rack::OAuth2] HTTP REQUEST FINISHED ======="
].each do |output|
expect(Rack::OAuth2.logger).to receive(:info).with output
end
request_filter.filter_response(request, response)
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/client_spec.rb 0000644 0000041 0000041 00000023106 12750322535 021563 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Client do
let :client do
Rack::OAuth2::Client.new(
identifier: 'client_id',
secret: 'client_secret',
host: 'server.example.com',
redirect_uri: 'https://client.example.com/callback'
)
end
subject { client }
its(:identifier) { should == 'client_id' }
its(:secret) { should == 'client_secret' }
its(:authorization_endpoint) { should == '/oauth2/authorize' }
its(:token_endpoint) { should == '/oauth2/token' }
context 'when identifier is missing' do
it do
expect { Rack::OAuth2::Client.new }.to raise_error AttrRequired::AttrMissing
end
end
describe '#authorization_uri' do
subject { client.authorization_uri }
it { should include 'https://server.example.com/oauth2/authorize' }
it { should include 'client_id=client_id' }
it { should include 'redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback' }
it { should include 'response_type=code' }
context 'when endpoints are absolute URIs' do
before do
client.authorization_endpoint = 'https://server2.example.com/oauth/authorize'
client.token_endpoint = 'https://server2.example.com/oauth/token'
end
it { should include 'https://server2.example.com/oauth/authorize' }
end
context 'when scheme is specified' do
before { client.scheme = 'http' }
it { should include 'http://server.example.com/oauth2/authorize' }
end
context 'when response_type is token' do
subject { client.authorization_uri(response_type: :token) }
it { should include 'response_type=token' }
end
context 'when response_type is an Array' do
subject { client.authorization_uri(response_type: [:token, :code]) }
it { should include 'response_type=token+code' }
end
context 'when scope is given' do
subject { client.authorization_uri(scope: [:scope1, :scope2]) }
it { should include 'scope=scope1+scope2' }
end
end
describe '#authorization_code=' do
before { client.authorization_code = 'code' }
subject { client.instance_variable_get('@grant') }
it { should be_instance_of Rack::OAuth2::Client::Grant::AuthorizationCode }
end
describe '#resource_owner_credentials=' do
before { client.resource_owner_credentials = 'username', 'password' }
subject { client.instance_variable_get('@grant') }
it { should be_instance_of Rack::OAuth2::Client::Grant::Password }
end
describe '#refresh_token=' do
before { client.refresh_token = 'refresh_token' }
subject { client.instance_variable_get('@grant') }
it { should be_instance_of Rack::OAuth2::Client::Grant::RefreshToken }
end
describe '#access_token!' do
subject { client.access_token! }
context 'when *args given' do
describe 'client authentication method' do
before do
client.authorization_code = 'code'
end
it 'should be Basic auth as default' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
request_header: {
'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ='
}
)
client.access_token!
end
context 'when other auth method specified' do
it 'should be body params' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
client_id: 'client_id',
client_secret: 'client_secret',
code: 'code',
grant_type: 'authorization_code',
redirect_uri: 'https://client.example.com/callback'
}
)
client.access_token! :client_auth_body
end
end
context 'when auth method is specified as Hash' do
it 'should be removed before sending request' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
client_id: 'client_id',
client_secret: 'client_secret',
code: 'code',
grant_type: 'authorization_code',
redirect_uri: 'https://client.example.com/callback'
}
)
client.access_token! client_auth_method: :body
end
end
end
describe 'scopes' do
context 'when scope option given' do
it 'should specify given scope' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
grant_type: 'client_credentials',
scope: 'a b'
}
)
client.access_token! scope: [:a, :b]
end
end
end
describe 'unknown params' do
it 'should be included in body params' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
grant_type: 'client_credentials',
resource: 'something'
}
)
client.access_token! resource: :something
end
end
end
context 'when bearer token is given' do
before do
client.authorization_code = 'code'
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json'
)
end
it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
its(:token_type) { should == :bearer }
its(:access_token) { should == 'access_token' }
its(:refresh_token) { should == 'refresh_token' }
its(:expires_in) { should == 3600 }
context 'when token type is "Bearer", not "bearer"' do
before do
client.authorization_code = 'code'
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/_Bearer.json'
)
end
it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
its(:token_type) { should == :bearer }
end
end
context 'when mac token is given' do
before do
client.authorization_code = 'code'
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/mac.json'
)
end
it { should be_instance_of Rack::OAuth2::AccessToken::MAC }
its(:token_type) { should == :mac }
its(:access_token) { should == 'access_token' }
its(:refresh_token) { should == 'refresh_token' }
its(:expires_in) { should == 3600 }
end
context 'when no-type token is given (JSON)' do
before do
client.authorization_code = 'code'
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/legacy.json'
)
end
it { should be_instance_of Rack::OAuth2::AccessToken::Legacy }
its(:token_type) { should == :legacy }
its(:access_token) { should == 'access_token' }
its(:refresh_token) { should == 'refresh_token' }
its(:expires_in) { should == 3600 }
end
context 'when no-type token is given (key-value)' do
before do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/legacy.txt'
)
end
it { should be_instance_of Rack::OAuth2::AccessToken::Legacy }
its(:token_type) { should == :legacy }
its(:access_token) { should == 'access_token' }
its(:expires_in) { should == 3600 }
context 'when expires_in is not given' do
before do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/legacy_without_expires_in.txt'
)
end
its(:expires_in) { should be_nil }
end
end
context 'when unknown-type token is given' do
before do
client.authorization_code = 'code'
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/unknown.json'
)
end
it do
expect { client.access_token! }.to raise_error(StandardError, 'Unknown Token Type')
end
end
context 'when error response is given' do
before do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'errors/invalid_request.json',
status: 400
)
end
it do
expect { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
end
end
context 'when no body given' do
context 'when error given' do
before do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'blank',
status: 400
)
end
it do
expect { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
end
end
end
end
context 'when no host info' do
let :client do
Rack::OAuth2::Client.new(
identifier: 'client_id',
secret: 'client_secret',
redirect_uri: 'https://client.example.com/callback'
)
end
describe '#authorization_uri' do
it do
expect { client.authorization_uri }.to raise_error 'No Host Info'
end
end
describe '#access_token!' do
it do
expect { client.access_token! }.to raise_error 'No Host Info'
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/util_spec.rb 0000644 0000041 0000041 00000004651 12750322535 021266 0 ustar www-data www-data require 'spec_helper.rb'
describe Rack::OAuth2::Util do
let :util do
Rack::OAuth2::Util
end
let :uri do
'http://client.example.com/callback'
end
describe '.rfc3986_encode' do
subject { util.rfc3986_encode '=+ .-/' }
it { should == '%3D%2B%20.-%2F' }
end
describe '.base64_encode' do
subject { util.base64_encode '=+ .-/' }
it { should == 'PSsgLi0v' }
end
describe '.compact_hash' do
subject { util.compact_hash k1: 'v1', k2: '', k3: nil }
it { should == {k1: 'v1'} }
end
describe '.parse_uri' do
context 'when String is given' do
it { util.parse_uri(uri).should be_a URI::Generic }
end
context 'when URI is given' do
it 'should be itself' do
_uri_ = URI.parse uri
util.parse_uri(_uri_).should be _uri_
end
end
context 'when invalid URI is given' do
it do
expect do
util.parse_uri '::'
end.to raise_error URI::InvalidURIError
end
end
context 'otherwise' do
it do
expect { util.parse_uri nil }.to raise_error StandardError
expect { util.parse_uri 123 }.to raise_error StandardError
end
end
end
describe '.redirect_uri' do
let(:base_uri) { 'http://client.example.com' }
let(:params) do
{k1: :v1, k2: ''}
end
subject { util.redirect_uri base_uri, location, params }
context 'when location = :fragment' do
let(:location) { :fragment }
it { should == "#{base_uri}##{util.compact_hash(params).to_query}" }
end
context 'when location = :query' do
let(:location) { :query }
it { should == "#{base_uri}?#{util.compact_hash(params).to_query}" }
end
end
describe '.uri_match?' do
context 'when invalid URI is given' do
it do
util.uri_match?('::', '::').should == false
util.uri_match?(123, 'http://client.example.com/other').should == false
util.uri_match?('http://client.example.com/other', nil).should == false
end
end
context 'when exactly same' do
it { util.uri_match?(uri, uri).should == true }
end
context 'when path prefix matches' do
it { util.uri_match?(uri, "#{uri}/deep_path").should == true }
end
context 'otherwise' do
it do
util.uri_match?(uri, 'http://client.example.com/other').should == false
util.uri_match?(uri, 'http://attacker.example.com/callback').should == false
end
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/access_token_spec.rb 0000644 0000041 0000041 00000004234 12750322535 022747 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2::AccessToken do
let :token do
Rack::OAuth2::AccessToken::Bearer.new(
access_token: 'access_token',
refresh_token: 'refresh_token',
expires_in: 3600,
scope: [:scope1, :scope2]
)
end
subject { token }
its(:access_token) { should == 'access_token' }
its(:refresh_token) { should == 'refresh_token' }
its(:expires_in) { should == 3600 }
its(:scope) { should == [:scope1, :scope2] }
its(:token_response) do
should == {
token_type: :bearer,
access_token: 'access_token',
refresh_token: 'refresh_token',
expires_in: 3600,
scope: 'scope1 scope2'
}
end
context 'when access_token is missing' do
it do
expect do
Rack::OAuth2::AccessToken::Bearer.new(
refresh_token: 'refresh_token',
expires_in: 3600,
scope: [:scope1, :scope2]
)
end.to raise_error AttrRequired::AttrMissing
end
end
context 'otherwise' do
it do
expect do
Rack::OAuth2::AccessToken::Bearer.new(
access_token: 'access_token'
)
end.not_to raise_error
end
end
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
[:get, :delete, :post, :put].each do |method|
describe method do
it 'should delegate to HTTPClient with Authenticator filter' do
expect(token.httpclient).to receive(method).with(resource_endpoint)
token.httpclient.request_filter.last.should be_a Rack::OAuth2::AccessToken::Authenticator
token.send method, resource_endpoint
end
end
context 'in debug mode' do
it do
Rack::OAuth2.debug do
token.httpclient.request_filter[-2].should be_a Rack::OAuth2::AccessToken::Authenticator
token.httpclient.request_filter.last.should be_a Rack::OAuth2::Debugger::RequestFilter
end
end
end
context 'when extension params given' do
subject do
Rack::OAuth2::AccessToken::Bearer.new(
access_token: 'access_token',
ex_key: :ex_value
)
end
its(:raw_attributes) { should include :ex_key }
end
end
end
rack-oauth2-1.4.0/spec/rack/oauth2/oauth2_spec.rb 0000644 0000041 0000041 00000004130 12750322535 021503 0 ustar www-data www-data require 'spec_helper'
describe Rack::OAuth2 do
subject { Rack::OAuth2 }
after { Rack::OAuth2.debugging = false }
its(:logger) { should be_a Logger }
its(:debugging?) { should == false }
describe '.debug!' do
before { Rack::OAuth2.debug! }
its(:debugging?) { should == true }
end
describe '.debug' do
it 'should enable debugging within given block' do
Rack::OAuth2.debug do
Rack::OAuth2.debugging?.should == true
end
Rack::OAuth2.debugging?.should == false
end
it 'should not force disable debugging' do
Rack::OAuth2.debug!
Rack::OAuth2.debug do
Rack::OAuth2.debugging?.should == true
end
Rack::OAuth2.debugging?.should == true
end
end
describe '.http_config' do
context 'when request_filter added' do
context 'when "debug!" is called' do
after { Rack::OAuth2.reset_http_config! }
it 'should put Debugger::RequestFilter at last' do
Rack::OAuth2.debug!
Rack::OAuth2.http_config do |config|
config.request_filter << Proc.new {}
end
Rack::OAuth2.http_client.request_filter.last.should be_instance_of Rack::OAuth2::Debugger::RequestFilter
end
it 'should reset_http_config' do
Rack::OAuth2.debug!
Rack::OAuth2.http_config do |config|
config.request_filter << Proc.new {}
end
size = Rack::OAuth2.http_client.request_filter.size
Rack::OAuth2.reset_http_config!
Rack::OAuth2.http_client.request_filter.size.should == size - 1
end
end
end
end
describe ".http_client" do
context "when local_http_config is used" do
it "should correctly set request_filter" do
clnt1 = Rack::OAuth2.http_client
clnt2 = Rack::OAuth2.http_client("my client") do |config|
config.request_filter << Proc.new {}
end
clnt3 = Rack::OAuth2.http_client
clnt1.request_filter.size.should == clnt3.request_filter.size
clnt1.request_filter.size.should == clnt2.request_filter.size - 1
end
end
end
end rack-oauth2-1.4.0/README.rdoc 0000644 0000041 0000041 00000004106 12750322535 015477 0 ustar www-data www-data = rack-oauth2
OAuth 2.0 Server & Client Library.
Both Bearer and MAC token type are supported.
{
}[http://travis-ci.org/nov/rack-oauth2]
The OAuth 2.0 Authorization Framework (RFC 6749)
http://www.rfc-editor.org/rfc/rfc6749.txt
The OAuth 2.0 Authorization Framework: Bearer Token Usage (RFC 6750)
http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-06
HTTP Authentication: MAC Access Authentication (draft 01)
http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01
== Installation
gem install rack-oauth2
== Resources
* View Source on GitHub (https://github.com/nov/rack-oauth2)
* Docs on GitHub (https://github.com/nov/rack-oauth2/wiki)
* Report Issues on GitHub (https://github.com/nov/rack-oauth2/issues)
== Sample Server Application (Rails3)
=== Bearer
Running on Heroku
https://rack-oauth2-sample.heroku.com
Source on GitHub
https://github.com/nov/rack-oauth2-sample
=== MAC
Running on Heroku
https://rack-oauth2-sample-mac.heroku.com
Source on GitHub
https://github.com/nov/rack-oauth2-sample-mac
== Sample Client
=== Common between Bearer and MAC
Authorization Request (request_type: 'code' and 'token')
https://gist.github.com/862393
Token Request (grant_type: 'client_credentials', 'password', 'authorization_code' and 'refresh_token')
https://gist.github.com/883541
=== Bearer
Resource Request (request both for resource owner resource and for client resource)
https://gist.github.com/883575
=== MAC
Resource Request (request both for resource owner resource and for client resource)
https://gist.github.com/933885
== Note on Patches/Pull Requests
* Fork the project.
* Make your feature addition or bug fix.
* Add tests for it. This is important so I don't break it in a
future version unintentionally.
* Commit, do not mess with rakefile, version, or history.
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
* Send me a pull request. Bonus points for topic branches.
== Copyright
Copyright (c) 2010 nov matake. See LICENSE for details.
rack-oauth2-1.4.0/.travis.yml 0000644 0000041 0000041 00000000113 12750322535 015774 0 ustar www-data www-data before_install:
- gem install bundler
rvm:
- 2.2.2
- 2.2.5
- 2.3.1 rack-oauth2-1.4.0/lib/ 0000755 0000041 0000041 00000000000 12750322535 014436 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/ 0000755 0000041 0000041 00000000000 12750322535 015356 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/ 0000755 0000041 0000041 00000000000 12750322535 016560 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/debugger.rb 0000644 0000041 0000041 00000000120 12750322535 020662 0 ustar www-data www-data Dir[File.dirname(__FILE__) + '/debugger/*.rb'].each do |file|
require file
end rack-oauth2-1.4.0/lib/rack/oauth2/server/ 0000755 0000041 0000041 00000000000 12750322535 020066 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize/ 0000755 0000041 0000041 00000000000 12750322535 022100 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize/code.rb 0000644 0000041 0000041 00000001564 12750322535 023345 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Authorize
class Code < Abstract::Handler
def call(env)
@request = Request.new env
@response = Response.new request
super
end
class Request < Authorize::Request
include Server::Extension::PKCE::AuthorizationRequest
def initialize(env)
super
@response_type = :code
attr_missing!
end
def error_params_location
:query
end
end
class Response < Authorize::Response
attr_required :code
def protocol_params
super.merge(code: code)
end
def protocol_params_location
:query
end
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize/extension.rb 0000644 0000041 0000041 00000000427 12750322535 024444 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Authorize
module Extension
# Define your extension in this namespace and load it explicitly.
# extension/code_and_token.rb would be good example for you.
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize/extension/ 0000755 0000041 0000041 00000000000 12750322535 024114 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize/extension/code_and_token.rb 0000644 0000041 0000041 00000001767 12750322535 027410 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Authorize
module Extension
class CodeAndToken < Abstract::Handler
class << self
def response_type_for?(response_type)
response_type.split.sort == ['code', 'token']
end
end
def call(env)
@request = Request.new env
@response = Response.new request
super
end
class Request < Authorize::Token::Request
include Server::Extension::PKCE::AuthorizationRequest
def initialize(env)
super
@response_type = [:code, :token]
attr_missing!
end
end
class Response < Authorize::Token::Response
attr_required :code
def protocol_params
super.merge(code: code)
end
end
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize/token.rb 0000644 0000041 0000041 00000001677 12750322535 023560 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Authorize
class Token < Abstract::Handler
def call(env)
@request = Request.new env
@response = Response.new request
super
end
class Request < Authorize::Request
def initialize(env)
super
@response_type = :token
attr_missing!
end
def error_params_location
:fragment
end
end
class Response < Authorize::Response
attr_required :access_token
def protocol_params
super.merge(
access_token.token_response.delete_if do |k, v|
k == :refresh_token
end
)
end
def protocol_params_location
:fragment
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize/error.rb 0000644 0000041 0000041 00000006315 12750322535 023563 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Authorize
module ErrorHandler
def self.included(klass)
klass.send :attr_accessor, :redirect_uri, :state, :protocol_params_location
end
def protocol_params
super.merge(state: state)
end
def redirect?
redirect_uri.present? &&
protocol_params_location.present?
end
def finish
if redirect?
super do |response|
response.redirect Util.redirect_uri(redirect_uri, protocol_params_location, protocol_params)
end
else
raise self
end
end
end
class BadRequest < Abstract::BadRequest
include ErrorHandler
end
class ServerError < Abstract::ServerError
include ErrorHandler
end
class TemporarilyUnavailable < Abstract::TemporarilyUnavailable
include ErrorHandler
end
module ErrorMethods
DEFAULT_DESCRIPTION = {
invalid_request: "The request is missing a required parameter, includes an unsupported parameter or parameter value, or is otherwise malformed.",
unauthorized_client: "The client is not authorized to use the requested response type.",
access_denied: "The end-user or authorization server denied the request.",
unsupported_response_type: "The requested response type is not supported by the authorization server.",
invalid_scope: "The requested scope is invalid, unknown, or malformed.",
server_error: "Internal Server Error",
temporarily_unavailable: "Service Unavailable"
}
def self.included(klass)
DEFAULT_DESCRIPTION.each do |error, default_description|
case error
when :server_error, :temporarily_unavailable
# NOTE: defined below
else
klass.class_eval <<-ERROR
def #{error}!(description = "#{default_description}", options = {})
bad_request! :#{error}, description, options
end
ERROR
end
end
end
def bad_request!(error = :bad_request, description = nil, options = {})
error! BadRequest, error, description, options
end
def server_error!(description = DEFAULT_DESCRIPTION[:server_error], options = {})
error! ServerError, :server_error, description, options
end
def temporarily_unavailable!(description = DEFAULT_DESCRIPTION[:temporarily_unavailable], options = {})
error! TemporarilyUnavailable, :temporarily_unavailable, description, options
end
private
def error!(klass, error, description, options)
exception = klass.new error, description, options
exception.protocol_params_location = error_params_location
exception.state = state
exception.redirect_uri = verified_redirect_uri
raise exception
end
end
Request.send :include, ErrorMethods
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/ 0000755 0000041 0000041 00000000000 12750322535 021715 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/mac/ 0000755 0000041 0000041 00000000000 12750322535 022455 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/mac/error.rb 0000644 0000041 0000041 00000001037 12750322535 024134 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Resource
class MAC
class Unauthorized < Resource::Unauthorized
def scheme
:MAC
end
end
module ErrorMethods
include Resource::ErrorMethods
def unauthorized!(error = nil, description = nil, options = {})
raise Unauthorized.new(error, description, options)
end
end
Request.send :include, ErrorMethods
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/bearer/ 0000755 0000041 0000041 00000000000 12750322535 023155 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/bearer/error.rb 0000644 0000041 0000041 00000001045 12750322535 024633 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Resource
class Bearer
class Unauthorized < Resource::Unauthorized
def scheme
:Bearer
end
end
module ErrorMethods
include Resource::ErrorMethods
def unauthorized!(error = nil, description = nil, options = {})
raise Unauthorized.new(error, description, options)
end
end
Request.send :include, ErrorMethods
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/bearer.rb 0000644 0000041 0000041 00000002303 12750322535 023500 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Resource
class Bearer < Resource
def call(env)
self.request = Request.new(env)
super
end
private
class Request < Resource::Request
def setup!
tokens = [access_token_in_header, access_token_in_payload].compact
@access_token = case Array(tokens).size
when 1
tokens.first
else
invalid_request!('Both Authorization header and payload includes access token.')
end
self
end
def oauth2?
(access_token_in_header || access_token_in_payload).present?
end
def access_token_in_header
if @auth_header.provided? && !@auth_header.parts.first.nil? && @auth_header.scheme.to_s == 'bearer'
@auth_header.params
else
nil
end
end
def access_token_in_payload
params['access_token']
end
end
end
end
end
end
end
require 'rack/oauth2/server/resource/bearer/error'
rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/mac.rb 0000644 0000041 0000041 00000001614 12750322535 023004 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Resource
class MAC < Resource
def call(env)
self.request = Request.new(env)
super
end
private
class Request < Resource::Request
attr_reader :nonce, :ts, :ext, :signature
def setup!
auth_params = Rack::Auth::Digest::Params.parse(@auth_header.params).with_indifferent_access
@access_token = auth_params[:id]
@nonce = auth_params[:nonce]
@ts = auth_params[:ts]
@ext = auth_params[:ext]
@signature = auth_params[:mac]
self
end
def oauth2?
@auth_header.provided? && @auth_header.scheme.to_s == 'mac'
end
end
end
end
end
end
end
require 'rack/oauth2/server/resource/mac/error'
rack-oauth2-1.4.0/lib/rack/oauth2/server/resource/error.rb 0000644 0000041 0000041 00000005317 12750322535 023401 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Resource
class BadRequest < Abstract::BadRequest
end
class Unauthorized < Abstract::Unauthorized
def scheme
raise 'Define me!'
end
def finish
super do |response|
self.realm ||= DEFAULT_REALM
header = response.header['WWW-Authenticate'] = "#{scheme} realm=\"#{realm}\""
if ErrorMethods::DEFAULT_DESCRIPTION.keys.include?(error)
header << ", error=\"#{error}\""
header << ", error_description=\"#{description}\"" if description.present?
header << ", error_uri=\"#{uri}\"" if uri.present?
end
end
end
end
class Forbidden < Abstract::Forbidden
attr_accessor :scope
def initialize(error = :forbidden, description = nil, options = {})
super
@scope = options[:scope]
end
def protocol_params
super.merge(scope: Array(scope).join(' '))
end
end
module ErrorMethods
DEFAULT_DESCRIPTION = {
invalid_request: "The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats the same parameter, uses more than one method for including an access token, or is otherwise malformed.",
invalid_token: "The access token provided is expired, revoked, malformed or invalid for other reasons.",
insufficient_scope: "The request requires higher privileges than provided by the access token."
}
def self.included(klass)
DEFAULT_DESCRIPTION.each do |error, default_description|
error_method = case error
when :invalid_request
:bad_request!
when :insufficient_scope
:forbidden!
else
:unauthorized!
end
klass.class_eval <<-ERROR
def #{error}!(description = "#{default_description}", options = {})
#{error_method} :#{error}, description, options
end
ERROR
end
end
def bad_request!(error, description = nil, options = {})
raise BadRequest.new(error, description, options)
end
def unauthorized!(error = nil, description = nil, options = {})
raise 'Define me!'
end
def forbidden!(error, description = nil, options = {})
raise Forbidden.new(error, description, options)
end
end
Request.send :include, ErrorMethods
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/abstract/ 0000755 0000041 0000041 00000000000 12750322535 021671 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/abstract/response.rb 0000644 0000041 0000041 00000000420 12750322535 024050 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Abstract
class Response < Rack::Response
include AttrRequired, AttrOptional
def initialize(request)
super([], 200, {})
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/abstract/request.rb 0000644 0000041 0000041 00000001427 12750322535 023712 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Abstract
class Request < Rack::Request
include AttrRequired, AttrOptional
attr_required :client_id
attr_optional :scope
def initialize(env)
super
@client_id ||= params['client_id']
@scope = Array(params['scope'].to_s.split(' '))
end
def attr_missing!
if params['client_id'].present? && @client_id != params['client_id']
invalid_request! 'Multiple client credentials are provided.'
end
super
rescue AttrRequired::AttrMissing => e
invalid_request! e.message, state: @state, redirect_uri: @redirect_uri
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/abstract/handler.rb 0000644 0000041 0000041 00000000644 12750322535 023637 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Abstract
class Handler
attr_accessor :authenticator, :request, :response
def initialize(&authenticator)
@authenticator = authenticator
end
def call(env)
@authenticator.call(@request, @response) if @authenticator
@response
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/abstract/error.rb 0000644 0000041 0000041 00000004061 12750322535 023350 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Abstract
class Error < StandardError
attr_accessor :status, :error, :description, :uri, :realm
def initialize(status, error, description = nil, options = {})
@status = status
@error = error
@description = description
@uri = options[:uri]
@realm = options[:realm]
super [error, description].compact.join(' :: ')
end
def protocol_params
{
error: error,
error_description: description,
error_uri: uri
}
end
def finish
response = Rack::Response.new
response.status = status
yield response if block_given?
unless response.redirect?
response.header['Content-Type'] = 'application/json'
response.write MultiJson.dump(Util.compact_hash(protocol_params))
end
response.finish
end
end
class BadRequest < Error
def initialize(error = :bad_request, description = nil, options = {})
super 400, error, description, options
end
end
class Unauthorized < Error
def initialize(error = :unauthorized, description = nil, options = {})
super 401, error, description, options
end
end
class Forbidden < Error
def initialize(error = :forbidden, description = nil, options = {})
super 403, error, description, options
end
end
class ServerError < Error
def initialize(error = :forbidden, description = nil, options = {})
super 500, error, description, options
end
end
class TemporarilyUnavailable < Error
def initialize(error = :forbidden, description = nil, options = {})
super 503, error, description, options
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/resource.rb 0000644 0000041 0000041 00000002424 12750322535 022244 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Resource < Abstract::Handler
ACCESS_TOKEN = 'rack.oauth2.access_token'
DEFAULT_REALM = 'Protected by OAuth 2.0'
attr_accessor :realm, :request
def initialize(app, realm = nil, &authenticator)
@app = app
@realm = realm
super(&authenticator)
end
def call(env)
if request.oauth2?
access_token = authenticate! request.setup!
env[ACCESS_TOKEN] = access_token
end
@app.call(env)
rescue Rack::OAuth2::Server::Abstract::Error => e
e.realm ||= realm
e.finish
end
private
def authenticate!(request)
@authenticator.call(request)
end
class Request < Rack::Request
attr_reader :access_token
def initialize(env)
@env = env
@auth_header = Rack::Auth::AbstractRequest.new(env)
end
def setup!
raise 'Define me!'
end
def oauth2?
raise 'Define me!'
end
end
end
end
end
end
require 'rack/oauth2/server/resource/error'
require 'rack/oauth2/server/resource/bearer'
require 'rack/oauth2/server/resource/mac'
rack-oauth2-1.4.0/lib/rack/oauth2/server/authorize.rb 0000644 0000041 0000041 00000006515 12750322535 022434 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Authorize < Abstract::Handler
def call(env)
request = Request.new(env)
response_type_for(request).new(&@authenticator).call(env).finish
rescue Rack::OAuth2::Server::Abstract::Error => e
e.finish
end
private
def response_type_for(request)
response_type = request.params['response_type'].to_s
case response_type
when 'code'
Code
when 'token'
Token
when ''
request.attr_missing!
else
extensions.detect do |extension|
extension.response_type_for? response_type
end || request.unsupported_response_type!
end
end
def extensions
Extension.constants.sort.collect do |key|
Extension.const_get key
end
end
class Request < Abstract::Request
attr_required :response_type
attr_optional :redirect_uri, :state
attr_accessor :verified_redirect_uri
def initialize(env)
super
# NOTE: Raise before redirect_uri is saved not to redirect back to unverified redirect_uri.
bad_request! if client_id.blank?
@redirect_uri = Util.parse_uri(params['redirect_uri']) if params['redirect_uri']
@state = params['state']
end
def verify_redirect_uri!(pre_registered, allow_partial_match = false)
@verified_redirect_uri = if redirect_uri.present?
verified = Array(pre_registered).any? do |_pre_registered_|
if allow_partial_match
Util.uri_match?(_pre_registered_, redirect_uri)
else
_pre_registered_.to_s == redirect_uri.to_s
end
end
if verified
redirect_uri
else
bad_request!
end
elsif pre_registered.present? && Array(pre_registered).size == 1 && !allow_partial_match
Array(pre_registered).first
else
bad_request!
end
self.verified_redirect_uri.to_s
end
def error_params_location
nil # => All errors are raised immediately and no error response are returned to client.
end
end
class Response < Abstract::Response
attr_required :redirect_uri
attr_optional :state, :approval
def initialize(request)
@state = request.state
super
end
def approved?
@approval
end
def approve!
@approval = true
end
def protocol_params
{state: state}
end
def redirect_uri_with_credentials
Util.redirect_uri(redirect_uri, protocol_params_location, protocol_params)
end
def finish
if approved?
attr_missing!
redirect redirect_uri_with_credentials
end
super
end
end
end
end
end
end
require 'rack/oauth2/server/authorize/code'
require 'rack/oauth2/server/authorize/token'
require 'rack/oauth2/server/authorize/extension'
require 'rack/oauth2/server/authorize/error'
rack-oauth2-1.4.0/lib/rack/oauth2/server/rails/ 0000755 0000041 0000041 00000000000 12750322535 021200 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/rails/authorize.rb 0000644 0000041 0000041 00000002026 12750322535 023537 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Rails
class Authorize < Server::Authorize
def initialize(app)
super()
@app = app
end
def call(env)
prepare_oauth_env env
@app.call env
rescue Rack::OAuth2::Server::Abstract::Error => e
e.finish
end
private
def prepare_oauth_env(env)
response_type = response_type_for(
Server::Authorize::Request.new(env)
).new
response_type.call(env)
response_type.response.extend ResponseExt
env[REQUEST] = response_type.request
env[RESPONSE] = response_type.response
rescue Rack::OAuth2::Server::Abstract::Error => e
env[ERROR] = e
end
module ResponseExt
include Rails::ResponseExt
def approve!
super
finish
end
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/rails/response_ext.rb 0000644 0000041 0000041 00000001527 12750322535 024250 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Rails
module ResponseExt
def redirect?
ensure_finish do
@response.redirect?
end
end
def location
ensure_finish do
super
end
end
def json
ensure_finish do
@response.body
end
end
def header
ensure_finish do
@header
end
end
def finish
@finished = true
super
end
private
def finished?
!!@finished
end
def ensure_finish
@status, @header, @response = finish unless finished?
yield
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/extension.rb 0000644 0000041 0000041 00000000053 12750322535 022425 0 ustar www-data www-data require 'rack/oauth2/server/extension/pkce' rack-oauth2-1.4.0/lib/rack/oauth2/server/extension/ 0000755 0000041 0000041 00000000000 12750322535 022102 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/extension/pkce.rb 0000644 0000041 0000041 00000002572 12750322535 023357 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Extension
module PKCE
module AuthorizationRequest
def self.included(klass)
klass.send :attr_optional, :code_challenge, :code_challenge_method
end
def initialize(env)
super
@code_challenge = params['code_challenge']
@code_challenge_method = params['code_challenge_method']
end
end
module TokenRequest
def self.included(klass)
klass.send :attr_optional, :code_verifier
end
def initialize(env)
super
@code_verifier = params['code_verifier']
end
def verify_code_verifier!(code_challenge, code_challenge_method = :S256)
if code_verifier.present? || code_challenge.present?
case code_challenge_method.try(:to_sym)
when :S256
code_challenge == Util.urlsafe_base64_encode(
OpenSSL::Digest::SHA256.digest(code_verifier.to_s)
) or invalid_grant!
when :plain
code_challenge == code_verifier or invalid_grant!
else
invalid_grant!
end
end
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token.rb 0000644 0000041 0000041 00000005015 12750322535 021534 0 ustar www-data www-data require 'rack/auth/basic'
module Rack
module OAuth2
module Server
class Token < Abstract::Handler
def call(env)
request = Request.new(env)
grant_type_for(request).new(&@authenticator).call(env).finish
rescue Rack::OAuth2::Server::Abstract::Error => e
e.finish
end
private
def grant_type_for(request)
case request.grant_type
when 'authorization_code'
AuthorizationCode
when 'password'
Password
when 'client_credentials'
ClientCredentials
when 'refresh_token'
RefreshToken
when URN::GrantType::JWT_BEARER
JWTBearer
when URN::GrantType::SAML2_BEARER
SAML2Bearer
when ''
request.attr_missing!
else
extensions.detect do |extension|
extension.grant_type_for? request.grant_type
end || request.unsupported_grant_type!
end
end
def extensions
Extension.constants.sort.collect do |key|
Extension.const_get key
end
end
class Request < Abstract::Request
attr_required :grant_type
attr_optional :client_secret
def initialize(env)
auth = Rack::Auth::Basic::Request.new(env)
if auth.provided? && auth.basic?
@client_id, @client_secret = auth.credentials
super
else
super
@client_secret = params['client_secret']
end
@grant_type = params['grant_type'].to_s
end
end
class Response < Abstract::Response
attr_required :access_token
def protocol_params
access_token.token_response
end
def finish
attr_missing!
write MultiJson.dump(Util.compact_hash(protocol_params))
header['Content-Type'] = 'application/json'
header['Cache-Control'] = 'no-store'
header['Pragma'] = 'no-cache'
super
end
end
end
end
end
end
require 'rack/oauth2/server/token/authorization_code'
require 'rack/oauth2/server/token/password'
require 'rack/oauth2/server/token/client_credentials'
require 'rack/oauth2/server/token/refresh_token'
require 'rack/oauth2/server/token/jwt_bearer'
require 'rack/oauth2/server/token/saml2_bearer'
require 'rack/oauth2/server/token/extension'
require 'rack/oauth2/server/token/error'
rack-oauth2-1.4.0/lib/rack/oauth2/server/token/ 0000755 0000041 0000041 00000000000 12750322535 021206 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/token/client_credentials.rb 0000644 0000041 0000041 00000000762 12750322535 025373 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
class ClientCredentials < Abstract::Handler
def call(env)
@request = Request.new(env)
@response = Response.new(request)
super
end
class Request < Token::Request
def initialize(env)
super
@grant_type = :client_credentials
attr_missing!
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token/password.rb 0000644 0000041 0000041 00000001155 12750322535 023377 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
class Password < Abstract::Handler
def call(env)
@request = Request.new(env)
@response = Response.new(request)
super
end
class Request < Token::Request
attr_required :username, :password
def initialize(env)
super
@grant_type = :password
@username = params['username']
@password = params['password']
attr_missing!
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token/saml2_bearer.rb 0000644 0000041 0000041 00000001155 12750322535 024073 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
class SAML2Bearer < Abstract::Handler
def call(env)
@request = Request.new env
@response = Response.new request
super
end
class Request < Token::Request
attr_required :assertion
attr_optional :client_id
def initialize(env)
super
@grant_type = URN::GrantType::SAML2_BEARER
@assertion = params['assertion']
attr_missing!
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token/extension.rb 0000644 0000041 0000041 00000000426 12750322535 023551 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
module Extension
# Define your extension in this namespace and load it explicitly.
# extension/assertion/example.rb would be good example for you.
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token/extension/ 0000755 0000041 0000041 00000000000 12750322535 023222 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/server/token/extension/example.rb 0000644 0000041 0000041 00000001603 12750322535 025202 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
module Extension
class Example < Abstract::Handler
GRANT_TYPE_URN = 'urn:ietf:params:oauth:grant-type:example'
class << self
def grant_type_for?(grant_type)
grant_type == GRANT_TYPE_URN
end
end
def call(env)
@request = Request.new env
@response = Response.new request
super
end
class Request < Token::Request
attr_required :assertion
attr_optional :client_id
def initialize(env)
super
@grant_type = GRANT_TYPE_URN
@assertion = params['assertion']
attr_missing!
end
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token/authorization_code.rb 0000644 0000041 0000041 00000001332 12750322535 025424 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
class AuthorizationCode < Abstract::Handler
def call(env)
@request = Request.new(env)
@response = Response.new(request)
super
end
class Request < Token::Request
include Server::Extension::PKCE::TokenRequest
attr_required :code
attr_optional :redirect_uri
def initialize(env)
super
@grant_type = :authorization_code
@code = params['code']
@redirect_uri = params['redirect_uri']
attr_missing!
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token/refresh_token.rb 0000644 0000041 0000041 00000001114 12750322535 024366 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
class RefreshToken < Abstract::Handler
def call(env)
@request = Request.new(env)
@response = Response.new(request)
super
end
class Request < Token::Request
attr_required :refresh_token
def initialize(env)
super
@grant_type = :refresh_token
@refresh_token = params['refresh_token']
attr_missing!
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/token/error.rb 0000644 0000041 0000041 00000004626 12750322535 022674 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
class BadRequest < Abstract::BadRequest
end
class Unauthorized < Abstract::Unauthorized
def finish
super do |response|
response.header['WWW-Authenticate'] = 'Basic realm="OAuth2 Token Endpoint"'
end
end
end
module ErrorMethods
DEFAULT_DESCRIPTION = {
invalid_request: "The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.",
invalid_client: "The client identifier provided is invalid, the client failed to authenticate, the client did not include its credentials, provided multiple client credentials, or used unsupported credentials type.",
invalid_grant: "The provided access grant is invalid, expired, or revoked (e.g. invalid assertion, expired authorization token, bad end-user password credentials, or mismatching authorization code and redirection URI).",
unauthorized_client: "The authenticated client is not authorized to use the access grant type provided.",
unsupported_grant_type: "The access grant included - its type or another attribute - is not supported by the authorization server.",
invalid_scope: "The requested scope is invalid, unknown, malformed, or exceeds the previously granted scope."
}
def self.included(klass)
DEFAULT_DESCRIPTION.each do |error, default_description|
error_method = if error == :invalid_client
:unauthorized!
else
:bad_request!
end
klass.class_eval <<-ERROR
def #{error}!(description = "#{default_description}", options = {})
#{error_method} :#{error}, description, options
end
ERROR
end
end
def bad_request!(error, description = nil, options = {})
raise BadRequest.new(error, description, options)
end
def unauthorized!(error, description = nil, options = {})
raise Unauthorized.new(error, description, options)
end
end
Request.send :include, ErrorMethods
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/server/token/jwt_bearer.rb 0000644 0000041 0000041 00000001151 12750322535 023655 0 ustar www-data www-data module Rack
module OAuth2
module Server
class Token
class JWTBearer < Abstract::Handler
def call(env)
@request = Request.new env
@response = Response.new request
super
end
class Request < Token::Request
attr_required :assertion
attr_optional :client_id
def initialize(env)
super
@grant_type = URN::GrantType::JWT_BEARER
@assertion = params['assertion']
attr_missing!
end
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server/rails.rb 0000644 0000041 0000041 00000000465 12750322535 021532 0 ustar www-data www-data module Rack
module OAuth2
module Server
module Rails
REQUEST = 'rack_oauth2.request'
RESPONSE = 'rack_oauth2.response'
ERROR = 'rack_oauth2.error'
end
end
end
end
require 'rack/oauth2/server/rails/response_ext'
require 'rack/oauth2/server/rails/authorize'
rack-oauth2-1.4.0/lib/rack/oauth2/server/abstract.rb 0000644 0000041 0000041 00000000266 12750322535 022222 0 ustar www-data www-data require 'rack/oauth2/server/abstract/handler'
require 'rack/oauth2/server/abstract/request'
require 'rack/oauth2/server/abstract/response'
require 'rack/oauth2/server/abstract/error' rack-oauth2-1.4.0/lib/rack/oauth2/access_token.rb 0000644 0000041 0000041 00000002353 12750322535 021551 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
include AttrRequired, AttrOptional
attr_required :access_token, :token_type, :httpclient
attr_optional :refresh_token, :expires_in, :scope
attr_accessor :raw_attributes
delegate :get, :patch, :post, :put, :delete, to: :httpclient
alias_method :to_s, :access_token
def initialize(attributes = {})
(required_attributes + optional_attributes).each do |key|
self.send :"#{key}=", attributes[key]
end
@raw_attributes = attributes
@token_type = self.class.name.demodulize.underscore.to_sym
@httpclient = Rack::OAuth2.http_client("#{self.class} (#{VERSION})") do |config|
config.request_filter << Authenticator.new(self)
end
attr_missing!
end
def token_response(options = {})
{
access_token: access_token,
refresh_token: refresh_token,
token_type: token_type,
expires_in: expires_in,
scope: Array(scope).join(' ')
}
end
end
end
end
require 'rack/oauth2/access_token/authenticator'
require 'rack/oauth2/access_token/bearer'
require 'rack/oauth2/access_token/mac'
require 'rack/oauth2/access_token/legacy'
rack-oauth2-1.4.0/lib/rack/oauth2/client.rb 0000644 0000041 0000041 00000011113 12750322535 020360 0 ustar www-data www-data module Rack
module OAuth2
class Client
include AttrRequired, AttrOptional
attr_required :identifier
attr_optional :secret, :redirect_uri, :scheme, :host, :port, :authorization_endpoint, :token_endpoint
def initialize(attributes = {})
(required_attributes + optional_attributes).each do |key|
self.send :"#{key}=", attributes[key]
end
@grant = Grant::ClientCredentials.new
@authorization_endpoint ||= '/oauth2/authorize'
@token_endpoint ||= '/oauth2/token'
attr_missing!
end
def authorization_uri(params = {})
params[:response_type] ||= :code
params[:response_type] = Array(params[:response_type]).join(' ')
params[:scope] = Array(params[:scope]).join(' ')
Util.redirect_uri absolute_uri_for(authorization_endpoint), :query, params.merge(
client_id: self.identifier,
redirect_uri: self.redirect_uri
)
end
def authorization_code=(code)
@grant = Grant::AuthorizationCode.new(
code: code,
redirect_uri: self.redirect_uri
)
end
def resource_owner_credentials=(credentials)
@grant = Grant::Password.new(
username: credentials.first,
password: credentials.last
)
end
def refresh_token=(token)
@grant = Grant::RefreshToken.new(
refresh_token: token
)
end
def jwt_bearer=(assertion)
@grant = Grant::JWTBearer.new(
assertion: assertion
)
end
def saml2_bearer=(assertion)
@grant = Grant::SAML2Bearer.new(
assertion: assertion
)
end
def subject_token=(subject_token, subject_token_type = URN::TokenType::JWT)
@grant = Grant::TokenExchange.new(
subject_token: subject_token,
subject_token_type: subject_token_type
)
end
def access_token!(*args)
headers, params = {}, @grant.as_json
# NOTE:
# Using Array#estract_options! for backward compatibility.
# Until v1.0.5, the first argument was 'client_auth_method' in scalar.
options = args.extract_options!
client_auth_method = args.first || options.delete(:client_auth_method) || :basic
params[:scope] = Array(options.delete(:scope)).join(' ') if options[:scope].present?
params.merge! options
if secret && client_auth_method == :basic
cred = ["#{identifier}:#{secret}"].pack('m').tr("\n", '')
headers.merge!(
'Authorization' => "Basic #{cred}"
)
else
params.merge!(
client_id: identifier,
client_secret: secret
)
end
handle_response do
Rack::OAuth2.http_client.post(
absolute_uri_for(token_endpoint),
Util.compact_hash(params),
headers
)
end
end
private
def absolute_uri_for(endpoint)
_endpoint_ = Util.parse_uri endpoint
_endpoint_.scheme ||= self.scheme || 'https'
_endpoint_.host ||= self.host
_endpoint_.port ||= self.port
raise 'No Host Info' unless _endpoint_.host
_endpoint_.to_s
end
def handle_response
response = yield
case response.status
when 200..201
handle_success_response response
else
handle_error_response response
end
end
def handle_success_response(response)
token_hash = parse_json response.body
case token_hash[:token_type].try(:downcase)
when 'bearer'
AccessToken::Bearer.new(token_hash)
when 'mac'
AccessToken::MAC.new(token_hash)
when nil
AccessToken::Legacy.new(token_hash)
else
raise 'Unknown Token Type'
end
rescue MultiJson::DecodeError
# NOTE: Facebook support (They don't use JSON as token response)
AccessToken::Legacy.new Rack::Utils.parse_nested_query(response.body).with_indifferent_access
end
def handle_error_response(response)
error = parse_json response.body
raise Error.new(response.status, error)
rescue MultiJson::DecodeError
raise Error.new(response.status, error: 'Unknown', error_description: response.body)
end
def parse_json(raw_json)
# MultiJson.parse('') returns nil when using MultiJson::Adapters::JsonGem
MultiJson.load(raw_json).try(:with_indifferent_access) || {}
end
end
end
end
require 'rack/oauth2/client/error'
require 'rack/oauth2/client/grant'
rack-oauth2-1.4.0/lib/rack/oauth2/access_token/ 0000755 0000041 0000041 00000000000 12750322535 021221 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/access_token/mac/ 0000755 0000041 0000041 00000000000 12750322535 021761 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/access_token/mac/signature.rb 0000644 0000041 0000041 00000001363 12750322535 024312 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
class MAC
class Signature < Verifier
attr_required :secret, :ts, :nonce, :method, :request_uri, :host, :port
attr_optional :ext, :query
def calculate
Rack::OAuth2::Util.base64_encode OpenSSL::HMAC.digest(
hash_generator,
secret,
normalized_request_string
)
end
def normalized_request_string
[
ts.to_i,
nonce,
method.to_s.upcase,
request_uri,
host,
port,
ext || '',
nil
].join("\n")
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/access_token/mac/sha256_hex_verifier.rb 0000644 0000041 0000041 00000000546 12750322535 026062 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
class MAC
class Sha256HexVerifier < Verifier
attr_optional :raw_body
def calculate
return nil unless raw_body.present?
OpenSSL::Digest::SHA256.new.digest(raw_body).unpack('H*').first
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/access_token/mac/verifier.rb 0000644 0000041 0000041 00000002231 12750322535 024117 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
class MAC
class Verifier
include AttrRequired, AttrOptional
attr_required :algorithm
class VerificationFailed < StandardError; end
def initialize(attributes = {})
(required_attributes + optional_attributes).each do |key|
self.send :"#{key}=", attributes[key]
end
attr_missing!
rescue AttrRequired::AttrMissing => e
raise VerificationFailed.new("#{self.class.name.demodulize} Invalid: #{e.message}")
end
def verify!(expected)
if expected == self.calculate
:verified
else
raise VerificationFailed.new("#{self.class.name.demodulize} Invalid")
end
end
private
def hash_generator
case algorithm.to_s
when 'hmac-sha-1'
OpenSSL::Digest::SHA1.new
when 'hmac-sha-256'
OpenSSL::Digest::SHA256.new
else
raise 'Unsupported Algorithm'
end
end
end
end
end
end
end
rack-oauth2-1.4.0/lib/rack/oauth2/access_token/bearer.rb 0000644 0000041 0000041 00000000341 12750322535 023004 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
class Bearer < AccessToken
def authenticate(request)
request.header["Authorization"] = "Bearer #{access_token}"
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/access_token/authenticator.rb 0000644 0000041 0000041 00000001107 12750322535 024417 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
class Authenticator
def initialize(token)
@token = token
end
# Callback called in HTTPClient (before sending a request)
# request:: HTTP::Message
def filter_request(request)
@token.authenticate(request)
end
# Callback called in HTTPClient (after received a response)
# response:: HTTP::Message
# request:: HTTP::Message
def filter_response(response, request)
# nothing to do
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/access_token/legacy.rb 0000644 0000041 0000041 00000000632 12750322535 023013 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
class Legacy < AccessToken
def initialize(attributes = {})
super
self.expires_in = (
self.expires_in ||
attributes[:expires]
).try(:to_i)
end
def authenticate(request)
request.header["Authorization"] = "OAuth #{access_token}"
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/access_token/mac.rb 0000644 0000041 0000041 00000006113 12750322535 022307 0 ustar www-data www-data module Rack
module OAuth2
class AccessToken
class MAC < AccessToken
attr_required :mac_key, :mac_algorithm
attr_optional :ts, :ext_verifier, :ts_expires_in
attr_reader :nonce, :signature, :ext
def initialize(attributes = {})
super(attributes)
@issued_at = Time.now.utc
@ts_expires_in ||= 5.minutes
end
def token_response
super.merge(
mac_key: mac_key,
mac_algorithm: mac_algorithm
)
end
def verify!(request)
if self.ext_verifier.present?
body = request.body.read
request.body.rewind # for future use
self.ext_verifier.new(
raw_body: body,
algorithm: self.mac_algorithm
).verify!(request.ext)
end
now = Time.now.utc.to_i
now = @ts.to_i if @ts.present?
raise Rack::OAuth2::AccessToken::MAC::Verifier::VerificationFailed.new("Request ts expired") if now - request.ts.to_i > @ts_expires_in.to_i
Signature.new(
secret: self.mac_key,
algorithm: self.mac_algorithm,
nonce: request.nonce,
method: request.request_method,
request_uri: request.fullpath,
host: request.host,
port: request.port,
ts: request.ts,
ext: request.ext
).verify!(request.signature)
rescue Verifier::VerificationFailed => e
request.invalid_token! e.message
end
def authenticate(request)
@nonce = generate_nonce
@ts_generated = @ts || Time.now.utc
if self.ext_verifier.present?
@ext = self.ext_verifier.new(
raw_body: request.body,
algorithm: self.mac_algorithm
).calculate
end
@signature = Signature.new(
secret: self.mac_key,
algorithm: self.mac_algorithm,
nonce: self.nonce,
method: request.header.request_method,
request_uri: request.header.create_query_uri,
host: request.header.request_uri.host,
port: request.header.request_uri.port,
ts: @ts_generated,
ext: @ext
).calculate
request.header['Authorization'] = authorization_header
end
private
def authorization_header
header = "MAC id=\"#{access_token}\""
header << ", nonce=\"#{nonce}\""
header << ", ts=\"#{@ts_generated.to_i}\""
header << ", mac=\"#{signature}\""
header << ", ext=\"#{ext}\"" if @ext.present?
header
end
def generate_nonce
[
(Time.now.utc - @issued_at).to_i,
SecureRandom.hex
].join(':')
end
end
end
end
end
require 'rack/oauth2/access_token/mac/verifier'
require 'rack/oauth2/access_token/mac/sha256_hex_verifier'
require 'rack/oauth2/access_token/mac/signature'
rack-oauth2-1.4.0/lib/rack/oauth2/client/ 0000755 0000041 0000041 00000000000 12750322535 020036 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/ 0000755 0000041 0000041 00000000000 12750322535 021151 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/token_exchange.rb 0000644 0000041 0000041 00000000431 12750322535 024456 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
class TokenExchange < Grant
attr_required :subject_token, :subject_token_type
def grant_type
URN::GrantType::TOKEN_EXCHANGE
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/client_credentials.rb 0000644 0000041 0000041 00000000216 12750322535 025330 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
class ClientCredentials < Grant
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/password.rb 0000644 0000041 0000041 00000000262 12750322535 023340 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
class Password < Grant
attr_required :username, :password
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/saml2_bearer.rb 0000644 0000041 0000041 00000000374 12750322535 024040 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
class SAML2Bearer < Grant
attr_required :assertion
def grant_type
URN::GrantType::SAML2_BEARER
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/authorization_code.rb 0000644 0000041 0000041 00000000322 12750322535 025365 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
class AuthorizationCode < Grant
attr_required :code
attr_optional :redirect_uri
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/refresh_token.rb 0000644 0000041 0000041 00000000260 12750322535 024332 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
class RefreshToken < Grant
attr_required :refresh_token
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/client/grant/jwt_bearer.rb 0000644 0000041 0000041 00000000370 12750322535 023622 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
class JWTBearer < Grant
attr_required :assertion
def grant_type
URN::GrantType::JWT_BEARER
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/client/grant.rb 0000644 0000041 0000041 00000001763 12750322535 021505 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Grant
include AttrRequired, AttrOptional
def initialize(attributes = {})
(required_attributes + optional_attributes).each do |key|
self.send "#{key}=", attributes[key]
end
attr_missing!
end
def grant_type
self.class.name.demodulize.underscore.to_sym
end
def as_json(options = {})
(required_attributes + optional_attributes).inject({
grant_type: grant_type
}) do |hash, key|
hash.merge! key => self.send(key)
end
end
end
end
end
end
require 'rack/oauth2/client/grant/authorization_code'
require 'rack/oauth2/client/grant/password'
require 'rack/oauth2/client/grant/client_credentials'
require 'rack/oauth2/client/grant/refresh_token'
require 'rack/oauth2/client/grant/jwt_bearer'
require 'rack/oauth2/client/grant/saml2_bearer'
require 'rack/oauth2/client/grant/token_exchange' rack-oauth2-1.4.0/lib/rack/oauth2/client/error.rb 0000644 0000041 0000041 00000000457 12750322535 021522 0 ustar www-data www-data module Rack
module OAuth2
class Client
class Error < StandardError
attr_accessor :status, :response
def initialize(status, response)
@status = status
@response = response
super response[:error_description]
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/debugger/ 0000755 0000041 0000041 00000000000 12750322535 020344 5 ustar www-data www-data rack-oauth2-1.4.0/lib/rack/oauth2/debugger/request_filter.rb 0000644 0000041 0000041 00000001471 12750322535 023731 0 ustar www-data www-data module Rack
module OAuth2
module Debugger
class RequestFilter
# Callback called in HTTPClient (before sending a request)
# request:: HTTP::Message
def filter_request(request)
started = "======= [Rack::OAuth2] HTTP REQUEST STARTED ======="
log started, request.dump
end
# Callback called in HTTPClient (after received a response)
# request:: HTTP::Message
# response:: HTTP::Message
def filter_response(request, response)
finished = "======= [Rack::OAuth2] HTTP REQUEST FINISHED ======="
log '-' * 50, response.dump, finished
end
private
def log(*outputs)
outputs.each do |output|
OAuth2.logger.info output
end
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/urn.rb 0000644 0000041 0000041 00000001643 12750322535 017715 0 ustar www-data www-data module Rack
module OAuth2
module URN
module TokenType
JWT = 'urn:ietf:params:oauth:token-type:jwt' # RFC7519
ACCESS_TOKEN = 'urn:ietf:params:oauth:token-type:access-token' # draft-ietf-oauth-token-exchange
REFRESH_TOKEN = 'urn:ietf:params:oauth:token-type:refresh-token' # draft-ietf-oauth-token-exchange
end
module GrantType
JWT_BEARER = 'urn:ietf:params:oauth:grant-type:jwt-bearer' # RFC7523
SAML2_BEARER = 'urn:ietf:params:oauth:grant-type:saml2-bearer' # RFC7522
TOKEN_EXCHANGE = 'urn:ietf:params:oauth:grant-type:token-exchange' # draft-ietf-oauth-token-exchange
end
module ClientAssertionType
JWT_BEARER = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' # RFC7523
SAML2_BEARER = 'urn:ietf:params:oauth:client-assertion-type:saml2-bearer' # RFC7522
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/util.rb 0000644 0000041 0000041 00000003036 12750322535 020064 0 ustar www-data www-data require 'base64'
module Rack
module OAuth2
module Util
class << self
def rfc3986_encode(text)
URI.encode(text, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
end
def base64_encode(text)
Base64.encode64(text).delete("\n")
end
def urlsafe_base64_encode(text)
Base64.urlsafe_encode64(text).delete('=')
end
def compact_hash(hash)
hash.reject do |key, value|
value.blank?
end
end
def parse_uri(uri)
case uri
when URI::Generic
uri
when String
URI.parse(uri)
else
raise "Invalid format of URI is given."
end
end
def redirect_uri(base_uri, location, params)
redirect_uri = parse_uri base_uri
case location
when :query
redirect_uri.query = [redirect_uri.query, Util.compact_hash(params).to_query].compact.join('&')
when :fragment
redirect_uri.fragment = Util.compact_hash(params).to_query
end
redirect_uri.to_s
end
def uri_match?(base, given)
base = parse_uri(base)
given = parse_uri(given)
base.path = '/' if base.path.blank?
given.path = '/' if given.path.blank?
[:scheme, :host, :port].all? do |key|
base.send(key) == given.send(key)
end && !!(/^#{base.path}/ =~ given.path)
rescue
false
end
end
end
end
end rack-oauth2-1.4.0/lib/rack/oauth2/server.rb 0000644 0000041 0000041 00000000340 12750322535 020410 0 ustar www-data www-data require 'rack/oauth2/server/abstract'
require 'rack/oauth2/server/extension'
require 'rack/oauth2/server/authorize'
require 'rack/oauth2/server/token'
require 'rack/oauth2/server/resource'
require 'rack/oauth2/server/rails'
rack-oauth2-1.4.0/lib/rack/oauth2.rb 0000644 0000041 0000041 00000003047 12750322535 017111 0 ustar www-data www-data require 'rack'
require 'multi_json'
require 'httpclient'
require 'logger'
require 'active_support'
require 'active_support/core_ext'
require 'attr_required'
require 'attr_optional'
module Rack
module OAuth2
VERSION = ::File.read(
::File.join(::File.dirname(__FILE__), '../../VERSION')
).strip
def self.logger
@@logger
end
def self.logger=(logger)
@@logger = logger
end
self.logger = ::Logger.new(STDOUT)
self.logger.progname = 'Rack::OAuth2'
def self.debugging?
@@debugging
end
def self.debugging=(boolean)
@@debugging = boolean
end
def self.debug!
self.debugging = true
end
def self.debug(&block)
original = self.debugging?
self.debugging = true
yield
ensure
self.debugging = original
end
self.debugging = false
def self.http_client(agent_name = "Rack::OAuth2 (#{VERSION})", &local_http_config)
_http_client_ = HTTPClient.new(
agent_name: agent_name
)
http_config.try(:call, _http_client_)
local_http_config.try(:call, _http_client_) unless local_http_config.nil?
_http_client_.request_filter << Debugger::RequestFilter.new if debugging?
_http_client_
end
def self.http_config(&block)
@@http_config ||= block
end
def self.reset_http_config!
@@http_config = nil
end
end
end
require 'rack/oauth2/urn'
require 'rack/oauth2/util'
require 'rack/oauth2/server'
require 'rack/oauth2/client'
require 'rack/oauth2/access_token'
require 'rack/oauth2/debugger'
rack-oauth2-1.4.0/.gitignore 0000644 0000041 0000041 00000000240 12750322535 015654 0 ustar www-data www-data ## MAC OS
.DS_Store
## TEXTMATE
*.tmproj
tmtags
## EMACS
*~
\#*
.\#*
## VIM
*.swp
## PROJECT::GENERAL
coverage*
rdoc
pkg
Gemfile.lock
## PROJECT::SPECIFIC
rack-oauth2-1.4.0/LICENSE 0000644 0000041 0000041 00000002036 12750322535 014676 0 ustar www-data www-data Copyright (c) 2010 nov matake
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
rack-oauth2-1.4.0/VERSION 0000644 0000041 0000041 00000000005 12750322535 014733 0 ustar www-data www-data 1.4.0 rack-oauth2-1.4.0/rack-oauth2.gemspec 0000644 0000041 0000041 00000002450 12750322535 017356 0 ustar www-data www-data Gem::Specification.new do |s|
s.name = "rack-oauth2"
s.version = File.read("VERSION")
s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
s.authors = ["nov matake"]
s.description = %q{OAuth 2.0 Server & Client Library. Both Bearer and MAC token type are supported.}
s.summary = %q{OAuth 2.0 Server & Client Library - Both Bearer and MAC token type are supported}
s.email = "nov@matake.jp"
s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
s.rdoc_options = ["--charset=UTF-8"]
s.homepage = "http://github.com/nov/rack-oauth2"
s.license = 'MIT'
s.require_paths = ["lib"]
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.add_runtime_dependency "rack", ">= 1.1"
s.add_runtime_dependency "multi_json", ">= 1.3.6"
s.add_runtime_dependency "httpclient", ">= 2.4"
s.add_runtime_dependency "activesupport", ">= 2.3"
s.add_runtime_dependency "attr_required", ">= 0.0.5"
s.add_development_dependency "rake", ">= 0.8"
s.add_development_dependency "simplecov"
s.add_development_dependency "rspec"
s.add_development_dependency "rspec-its"
s.add_development_dependency "webmock", "< 1.24"
end
rack-oauth2-1.4.0/.document 0000644 0000041 0000041 00000000074 12750322535 015510 0 ustar www-data www-data README.rdoc
lib/**/*.rb
bin/*
features/**/*.feature
LICENSE