pax_global_header 0000666 0000000 0000000 00000000064 14310224506 0014507 g ustar 00root root 0000000 0000000 52 comment=1ba7dc7ba4360dedfa12643bf12dbaae4e6293c1
rack-oauth2-1.21.3/ 0000775 0000000 0000000 00000000000 14310224506 0013713 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/.document 0000664 0000000 0000000 00000000074 14310224506 0015533 0 ustar 00root root 0000000 0000000 README.rdoc
lib/**/*.rb
bin/*
features/**/*.feature
LICENSE
rack-oauth2-1.21.3/.github/ 0000775 0000000 0000000 00000000000 14310224506 0015253 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/.github/FUNDING.yml 0000664 0000000 0000000 00000000073 14310224506 0017070 0 ustar 00root root 0000000 0000000 # These are supported funding model platforms
github: nov
rack-oauth2-1.21.3/.github/workflows/ 0000775 0000000 0000000 00000000000 14310224506 0017310 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/.github/workflows/spec.yml 0000664 0000000 0000000 00000001141 14310224506 0020762 0 ustar 00root root 0000000 0000000 name: Spec
on:
push:
pull_request:
permissions:
contents: read
jobs:
spec:
strategy:
matrix:
os: ['ubuntu-20.04']
ruby-version: ['2.6', '2.7', '3.0', '3.1']
# ubuntu 22.04 only supports ssl 3 and thus only ruby 3.1
include:
- os: 'ubuntu-22.04'
ruby-version: '3.1'
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true
- name: Run Specs
run: bundle exec rake spec
rack-oauth2-1.21.3/.gitignore 0000664 0000000 0000000 00000000240 14310224506 0015677 0 ustar 00root root 0000000 0000000 ## MAC OS
.DS_Store
## TEXTMATE
*.tmproj
tmtags
## EMACS
*~
\#*
.\#*
## VIM
*.swp
## PROJECT::GENERAL
coverage*
rdoc
pkg
Gemfile.lock
## PROJECT::SPECIFIC
rack-oauth2-1.21.3/.rspec 0000664 0000000 0000000 00000000037 14310224506 0015030 0 ustar 00root root 0000000 0000000 --color
--format=documentation
rack-oauth2-1.21.3/.travis.yml 0000664 0000000 0000000 00000000126 14310224506 0016023 0 ustar 00root root 0000000 0000000 before_install:
- gem install bundler
rvm:
- 2.6.10
- 2.7.6
- 3.0.4
- 3.1.2 rack-oauth2-1.21.3/Gemfile 0000664 0000000 0000000 00000000140 14310224506 0015201 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
platforms :jruby do
gem 'jruby-openssl', '>= 0.7'
end
gemspec
rack-oauth2-1.21.3/LICENSE 0000664 0000000 0000000 00000002036 14310224506 0014721 0 ustar 00root root 0000000 0000000 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.21.3/README.rdoc 0000664 0000000 0000000 00000003720 14310224506 0015523 0 ustar 00root root 0000000 0000000 = 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
Source on GitHub
https://github.com/nov/rack-oauth2-sample
=== MAC
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.21.3/Rakefile 0000664 0000000 0000000 00000000620 14310224506 0015356 0 ustar 00root root 0000000 0000000 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.21.3/VERSION 0000664 0000000 0000000 00000000006 14310224506 0014757 0 ustar 00root root 0000000 0000000 1.21.3 rack-oauth2-1.21.3/lib/ 0000775 0000000 0000000 00000000000 14310224506 0014461 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/ 0000775 0000000 0000000 00000000000 14310224506 0015401 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2.rb 0000664 0000000 0000000 00000003336 14310224506 0017135 0 ustar 00root root 0000000 0000000 require 'rack'
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
)
# NOTE: httpclient gem seems stopped maintaining root certtificate set, use OS default.
_http_client_.ssl_config.clear_cert_store
_http_client_.ssl_config.cert_store.set_default_paths
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.21.3/lib/rack/oauth2/ 0000775 0000000 0000000 00000000000 14310224506 0016603 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/access_token.rb 0000664 0000000 0000000 00000002450 14310224506 0021572 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class AccessToken
include AttrRequired, AttrOptional
attr_required :access_token, :token_type
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
attr_missing!
end
def httpclient
@httpclient ||= Rack::OAuth2.http_client("#{self.class} (#{VERSION})") do |config|
config.request_filter << Authenticator.new(self)
end
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'
require 'rack/oauth2/access_token/mtls'
rack-oauth2-1.21.3/lib/rack/oauth2/access_token/ 0000775 0000000 0000000 00000000000 14310224506 0021244 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/access_token/authenticator.rb 0000664 0000000 0000000 00000001107 14310224506 0024442 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/access_token/bearer.rb 0000664 0000000 0000000 00000000661 14310224506 0023034 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class AccessToken
class Bearer < AccessToken
def authenticate(request)
request.header["Authorization"] = "Bearer #{access_token}"
end
def to_mtls(attributes = {})
(required_attributes + optional_attributes).each do |key|
attributes[key] = self.send(key)
end
MTLS.new attributes
end
end
end
end
end
rack-oauth2-1.21.3/lib/rack/oauth2/access_token/legacy.rb 0000664 0000000 0000000 00000000632 14310224506 0023036 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/access_token/mac.rb 0000664 0000000 0000000 00000006113 14310224506 0022332 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/access_token/mac/ 0000775 0000000 0000000 00000000000 14310224506 0022004 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/access_token/mac/sha256_hex_verifier.rb 0000664 0000000 0000000 00000000546 14310224506 0026105 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/access_token/mac/signature.rb 0000664 0000000 0000000 00000001363 14310224506 0024335 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/access_token/mac/verifier.rb 0000664 0000000 0000000 00000002231 14310224506 0024142 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/access_token/mtls.rb 0000664 0000000 0000000 00000000565 14310224506 0022556 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class AccessToken
class MTLS < Bearer
attr_required :private_key, :certificate
def initialize(attributes = {})
super
self.token_type = :bearer
httpclient.ssl_config.client_key = private_key
httpclient.ssl_config.client_cert = certificate
end
end
end
end
end
rack-oauth2-1.21.3/lib/rack/oauth2/client.rb 0000664 0000000 0000000 00000016475 14310224506 0020423 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class Client
include AttrRequired, AttrOptional
attr_required :identifier
attr_optional :secret, :private_key, :certificate, :redirect_uri, :scheme, :host, :port, :authorization_endpoint, :token_endpoint, :revocation_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[:redirect_uri] ||= self.redirect_uri
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
)
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 force_token_type!(token_type)
@forced_token_type = token_type.to_s
end
def access_token!(*args)
headers, params, http_client, options = authenticated_context_from(*args)
params[:scope] = Array(options.delete(:scope)).join(' ') if options[:scope].present?
params.merge! @grant.as_json
params.merge! options
handle_response do
http_client.post(
absolute_uri_for(token_endpoint),
Util.compact_hash(params),
headers
)
end
end
def revoke!(*args)
headers, params, http_client, options = authenticated_context_from(*args)
params.merge! case
when access_token = options.delete(:access_token)
{
token: access_token,
token_type_hint: :access_token
}
when refresh_token = options.delete(:refresh_token)
{
token: refresh_token,
token_type_hint: :refresh_token
}
when @grant.is_a?(Grant::RefreshToken)
{
token: @grant.refresh_token,
token_type_hint: :refresh_token
}
when options[:token].blank?
raise ArgumentError, 'One of "token", "access_token" and "refresh_token" is required'
end
params.merge! options
handle_revocation_response do
http_client.post(
absolute_uri_for(revocation_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 authenticated_context_from(*args)
headers, params = {}, {}
http_client = Rack::OAuth2.http_client
# NOTE:
# Using Array#extract_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).try(:to_sym) || :basic
case client_auth_method
when :basic
cred = Base64.strict_encode64 [
Util.www_form_url_encode(identifier),
Util.www_form_url_encode(secret)
].join(':')
headers.merge!(
'Authorization' => "Basic #{cred}"
)
when :basic_without_www_form_urlencode
cred = ["#{identifier}:#{secret}"].pack('m').tr("\n", '')
headers.merge!(
'Authorization' => "Basic #{cred}"
)
when :jwt_bearer
params.merge!(
client_assertion_type: URN::ClientAssertionType::JWT_BEARER
)
# NOTE: optionally auto-generate client_assertion.
params[:client_assertion] = if options[:client_assertion].present?
options.delete(:client_assertion)
else
require 'json/jwt'
JSON::JWT.new(
iss: identifier,
sub: identifier,
aud: absolute_uri_for(token_endpoint),
jti: SecureRandom.hex(16),
iat: Time.now,
exp: 3.minutes.from_now
).sign(private_key || secret).to_s
end
when :saml2_bearer
params.merge!(
client_assertion_type: URN::ClientAssertionType::SAML2_BEARER
)
when :mtls
params.merge!(
client_id: identifier
)
http_client.ssl_config.client_key = private_key
http_client.ssl_config.client_cert = certificate
else
params.merge!(
client_id: identifier,
client_secret: secret
)
end
[headers, params, http_client, options]
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_revocation_response
response = yield
case response.status
when 200..201
:success
else
handle_error_response response
end
end
def handle_success_response(response)
token_hash = JSON.parse(response.body).with_indifferent_access
case (@forced_token_type || 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 JSON::ParserError
# 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 = JSON.parse(response.body).with_indifferent_access
raise Error.new(response.status, error)
rescue JSON::ParserError
raise Error.new(response.status, error: 'Unknown', error_description: response.body)
end
end
end
end
require 'rack/oauth2/client/error'
require 'rack/oauth2/client/grant'
rack-oauth2-1.21.3/lib/rack/oauth2/client/ 0000775 0000000 0000000 00000000000 14310224506 0020061 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/client/error.rb 0000664 0000000 0000000 00000000565 14310224506 0021545 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class Client
class Error < StandardError
attr_accessor :status, :response
def initialize(status, response)
@status = status
@response = response
message = [response[:error], response[:error_description]].compact.join(' :: ')
super message
end
end
end
end
end
rack-oauth2-1.21.3/lib/rack/oauth2/client/grant.rb 0000664 0000000 0000000 00000001763 14310224506 0021530 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/client/grant/ 0000775 0000000 0000000 00000000000 14310224506 0021174 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/client/grant/authorization_code.rb 0000664 0000000 0000000 00000000322 14310224506 0025410 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/client/grant/client_credentials.rb 0000664 0000000 0000000 00000000216 14310224506 0025353 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class Client
class Grant
class ClientCredentials < Grant
end
end
end
end
end rack-oauth2-1.21.3/lib/rack/oauth2/client/grant/jwt_bearer.rb 0000664 0000000 0000000 00000000370 14310224506 0023645 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/client/grant/password.rb 0000664 0000000 0000000 00000000262 14310224506 0023363 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class Client
class Grant
class Password < Grant
attr_required :username, :password
end
end
end
end
end rack-oauth2-1.21.3/lib/rack/oauth2/client/grant/refresh_token.rb 0000664 0000000 0000000 00000000260 14310224506 0024355 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
class Client
class Grant
class RefreshToken < Grant
attr_required :refresh_token
end
end
end
end
end rack-oauth2-1.21.3/lib/rack/oauth2/client/grant/saml2_bearer.rb 0000664 0000000 0000000 00000000374 14310224506 0024063 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/client/grant/token_exchange.rb 0000664 0000000 0000000 00000000431 14310224506 0024501 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/debugger.rb 0000664 0000000 0000000 00000000120 14310224506 0020705 0 ustar 00root root 0000000 0000000 Dir[File.dirname(__FILE__) + '/debugger/*.rb'].each do |file|
require file
end rack-oauth2-1.21.3/lib/rack/oauth2/debugger/ 0000775 0000000 0000000 00000000000 14310224506 0020367 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/debugger/request_filter.rb 0000664 0000000 0000000 00000001471 14310224506 0023754 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server.rb 0000664 0000000 0000000 00000000340 14310224506 0020433 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/ 0000775 0000000 0000000 00000000000 14310224506 0020111 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/abstract.rb 0000664 0000000 0000000 00000000266 14310224506 0022245 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/abstract/ 0000775 0000000 0000000 00000000000 14310224506 0021714 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/abstract/error.rb 0000664 0000000 0000000 00000004200 14310224506 0023366 0 ustar 00root root 0000000 0000000 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.headers['Content-Type'] = 'application/json'
response.write Util.compact_hash(protocol_params).to_json
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 = {})
@skip_www_authenticate = options[:skip_www_authenticate]
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 = :server_error, description = nil, options = {})
super 500, error, description, options
end
end
class TemporarilyUnavailable < Error
def initialize(error = :temporarily_unavailable, description = nil, options = {})
super 503, error, description, options
end
end
end
end
end
end
rack-oauth2-1.21.3/lib/rack/oauth2/server/abstract/handler.rb 0000664 0000000 0000000 00000001456 14310224506 0023664 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
module Server
module Abstract
class Handler
attr_accessor :authenticator, :request, :response
def initialize(&authenticator)
@authenticator = authenticator
end
def call(env)
# NOTE:
# Rack middleware is initialized only on the first request of the process.
# So any instance variables are acts like class variables, and modifying them in call() isn't thread-safe.
# ref.) http://stackoverflow.com/questions/23028226/rack-middleware-and-thread-safety
dup._call(env)
end
def _call(env)
@authenticator.call(@request, @response) if @authenticator
@response
end
end
end
end
end
end rack-oauth2-1.21.3/lib/rack/oauth2/server/abstract/request.rb 0000664 0000000 0000000 00000001427 14310224506 0023735 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/abstract/response.rb 0000664 0000000 0000000 00000000420 14310224506 0024073 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/authorize.rb 0000664 0000000 0000000 00000007120 14310224506 0022450 0 ustar 00root root 0000000 0000000 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
include Server::Extension::ResponseMode::AuthorizationRequest
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.
invalid_request! '"client_id" missing' if client_id.blank?
@redirect_uri = Util.parse_uri(params['redirect_uri']) if params['redirect_uri']
@response_mode = params['response_mode']
@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
invalid_request! '"redirect_uri" mismatch'
end
elsif pre_registered.present? && Array(pre_registered).size == 1 && !allow_partial_match
Array(pre_registered).first
else
invalid_request! '"redirect_uri" missing'
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, :session_state, :approval
def initialize(request)
@state = request.state
super
end
def approved?
@approval
end
def approve!
@approval = true
end
def protocol_params
{state: state, session_state: session_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.21.3/lib/rack/oauth2/server/authorize/ 0000775 0000000 0000000 00000000000 14310224506 0022123 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/authorize/code.rb 0000664 0000000 0000000 00000001565 14310224506 0023371 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/authorize/error.rb 0000664 0000000 0000000 00000006315 14310224506 0023606 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/authorize/extension.rb 0000664 0000000 0000000 00000000427 14310224506 0024467 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/authorize/extension/ 0000775 0000000 0000000 00000000000 14310224506 0024137 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/authorize/extension/code_and_token.rb 0000664 0000000 0000000 00000001770 14310224506 0027425 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/authorize/token.rb 0000664 0000000 0000000 00000001700 14310224506 0023566 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/extension.rb 0000664 0000000 0000000 00000000140 14310224506 0022445 0 ustar 00root root 0000000 0000000 require 'rack/oauth2/server/extension/pkce'
require 'rack/oauth2/server/extension/response_mode' rack-oauth2-1.21.3/lib/rack/oauth2/server/extension/ 0000775 0000000 0000000 00000000000 14310224506 0022125 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/extension/pkce.rb 0000664 0000000 0000000 00000002572 14310224506 0023402 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/extension/response_mode.rb 0000664 0000000 0000000 00000000645 14310224506 0025321 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
module Server
module Extension
module ResponseMode
module AuthorizationRequest
def self.included(klass)
klass.send :attr_optional, :response_mode
end
def initialize(env)
super
@response_mode = params['response_mode']
end
end
end
end
end
end
end rack-oauth2-1.21.3/lib/rack/oauth2/server/rails.rb 0000664 0000000 0000000 00000000465 14310224506 0021555 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/rails/ 0000775 0000000 0000000 00000000000 14310224506 0021223 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/rails/authorize.rb 0000664 0000000 0000000 00000002030 14310224506 0023555 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/rails/response_ext.rb 0000664 0000000 0000000 00000001477 14310224506 0024277 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
module Server
module Rails
module ResponseExt
def redirect?
ensure_finish do
super
end
end
def location
ensure_finish do
super
end
end
def json
ensure_finish do
@body
end
end
def headers
ensure_finish do
@headers
end
end
def finish
@finished = true
super
end
private
def finished?
!!@finished
end
def ensure_finish
@status, @headers, @body = finish unless finished?
yield
end
end
end
end
end
end
rack-oauth2-1.21.3/lib/rack/oauth2/server/resource.rb 0000664 0000000 0000000 00000002425 14310224506 0022270 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/resource/ 0000775 0000000 0000000 00000000000 14310224506 0021740 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/resource/bearer.rb 0000664 0000000 0000000 00000002304 14310224506 0023524 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/resource/bearer/ 0000775 0000000 0000000 00000000000 14310224506 0023200 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/resource/bearer/error.rb 0000664 0000000 0000000 00000001045 14310224506 0024656 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/resource/error.rb 0000664 0000000 0000000 00000005324 14310224506 0023422 0 ustar 00root root 0000000 0000000 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
headers = response.headers['WWW-Authenticate'] = "#{scheme} realm=\"#{realm}\""
if ErrorMethods::DEFAULT_DESCRIPTION.keys.include?(error)
headers << ", error=\"#{error}\""
headers << ", error_description=\"#{description}\"" if description.present?
headers << ", 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.21.3/lib/rack/oauth2/server/resource/mac.rb 0000664 0000000 0000000 00000001615 14310224506 0023030 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/resource/mac/ 0000775 0000000 0000000 00000000000 14310224506 0022500 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/resource/mac/error.rb 0000664 0000000 0000000 00000001037 14310224506 0024157 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token.rb 0000664 0000000 0000000 00000006103 14310224506 0021556 0 ustar 00root root 0000000 0000000 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, :client_assertion, :client_assertion_type
def initialize(env)
auth = Rack::Auth::Basic::Request.new(env)
if auth.provided? && auth.basic?
@client_id, @client_secret = auth.credentials.map do |cred|
Util.www_form_url_decode cred
end
super
else
super
@client_secret = params['client_secret']
@client_assertion = params['client_assertion']
@client_assertion_type = params['client_assertion_type']
if client_assertion.present? && client_assertion_type == URN::ClientAssertionType::JWT_BEARER
require 'json/jwt'
@client_id = JSON::JWT.decode(
client_assertion,
:skip_verification
)[:sub] rescue nil
end
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 Util.compact_hash(protocol_params).to_json
headers['Content-Type'] = 'application/json'
headers['Cache-Control'] = 'no-store'
headers['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.21.3/lib/rack/oauth2/server/token/ 0000775 0000000 0000000 00000000000 14310224506 0021231 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/token/authorization_code.rb 0000664 0000000 0000000 00000001333 14310224506 0025450 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token/client_credentials.rb 0000664 0000000 0000000 00000000763 14310224506 0025417 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token/error.rb 0000664 0000000 0000000 00000004727 14310224506 0022721 0 ustar 00root root 0000000 0000000 module Rack
module OAuth2
module Server
class Token
class BadRequest < Abstract::BadRequest
end
class Unauthorized < Abstract::Unauthorized
def finish
super do |response|
unless @skip_www_authenticate
response.headers['WWW-Authenticate'] = 'Basic realm="OAuth2 Token Endpoint"'
end
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.21.3/lib/rack/oauth2/server/token/extension.rb 0000664 0000000 0000000 00000000426 14310224506 0023574 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token/extension/ 0000775 0000000 0000000 00000000000 14310224506 0023245 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/lib/rack/oauth2/server/token/extension/example.rb 0000664 0000000 0000000 00000001604 14310224506 0025226 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token/jwt_bearer.rb 0000664 0000000 0000000 00000001152 14310224506 0023701 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token/password.rb 0000664 0000000 0000000 00000001156 14310224506 0023423 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token/refresh_token.rb 0000664 0000000 0000000 00000001115 14310224506 0024412 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/server/token/saml2_bearer.rb 0000664 0000000 0000000 00000001156 14310224506 0024117 0 ustar 00root root 0000000 0000000 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.21.3/lib/rack/oauth2/urn.rb 0000664 0000000 0000000 00000001533 14310224506 0017736 0 ustar 00root root 0000000 0000000 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' # RFC8693
REFRESH_TOKEN = 'urn:ietf:params:oauth:token-type:refresh_token' # RFC8693
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' # RFC8693
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.21.3/lib/rack/oauth2/util.rb 0000664 0000000 0000000 00000003260 14310224506 0020106 0 ustar 00root root 0000000 0000000 require 'base64'
module Rack
module OAuth2
module Util
class << self
def www_form_url_encode(text)
URI.encode_www_form_component(text)
end
def www_form_url_decode(text)
URI.decode_www_form_component(text)
end
def base64_encode(text)
Base64.encode64(text).delete("\n")
end
def urlsafe_base64_encode(text)
Base64.urlsafe_encode64(text, padding: false)
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
encoded_response_params = Util.compact_hash(params).to_query.gsub('+', '%20')
case location
when :query
redirect_uri.query = [redirect_uri.query, encoded_response_params].compact.join('&')
when :fragment
redirect_uri.fragment = encoded_response_params
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.21.3/rack-oauth2.gemspec 0000664 0000000 0000000 00000002257 14310224506 0017406 0 ustar 00root root 0000000 0000000 Gem::Specification.new do |s|
s.name = 'rack-oauth2'
s.version = File.read('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 = 'https://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', '>= 2.1.0'
s.add_runtime_dependency 'httpclient'
s.add_runtime_dependency 'activesupport'
s.add_runtime_dependency 'attr_required'
s.add_runtime_dependency 'json-jwt', '>= 1.11.0'
s.add_development_dependency 'rake'
s.add_development_dependency 'simplecov'
s.add_development_dependency 'rspec'
s.add_development_dependency 'rspec-its'
s.add_development_dependency 'webmock'
s.add_development_dependency 'rexml'
end
rack-oauth2-1.21.3/spec/ 0000775 0000000 0000000 00000000000 14310224506 0014645 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/helpers/ 0000775 0000000 0000000 00000000000 14310224506 0016307 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/helpers/time.rb 0000664 0000000 0000000 00000000506 14310224506 0017573 0 ustar 00root root 0000000 0000000 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.21.3/spec/helpers/webmock_helper.rb 0000664 0000000 0000000 00000001635 14310224506 0021627 0 ustar 00root root 0000000 0000000 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.21.3/spec/mock_response/ 0000775 0000000 0000000 00000000000 14310224506 0017514 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/mock_response/blank 0000664 0000000 0000000 00000000000 14310224506 0020514 0 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/mock_response/errors/ 0000775 0000000 0000000 00000000000 14310224506 0021030 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/mock_response/errors/invalid_request.json 0000664 0000000 0000000 00000000112 14310224506 0025113 0 ustar 00root root 0000000 0000000 {
"error":"invalid_request",
"error_description":"error description"
} rack-oauth2-1.21.3/spec/mock_response/resources/ 0000775 0000000 0000000 00000000000 14310224506 0021526 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/mock_response/resources/fake.txt 0000664 0000000 0000000 00000000004 14310224506 0023167 0 ustar 00root root 0000000 0000000 fake rack-oauth2-1.21.3/spec/mock_response/tokens/ 0000775 0000000 0000000 00000000000 14310224506 0021017 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/mock_response/tokens/_Bearer.json 0000664 0000000 0000000 00000000164 14310224506 0023252 0 ustar 00root root 0000000 0000000 {
"access_token":"access_token",
"refresh_token":"refresh_token",
"token_type":"Bearer",
"expires_in":3600
} rack-oauth2-1.21.3/spec/mock_response/tokens/bearer.json 0000664 0000000 0000000 00000000164 14310224506 0023153 0 ustar 00root root 0000000 0000000 {
"access_token":"access_token",
"refresh_token":"refresh_token",
"token_type":"bearer",
"expires_in":3600
} rack-oauth2-1.21.3/spec/mock_response/tokens/legacy.json 0000664 0000000 0000000 00000000133 14310224506 0023153 0 ustar 00root root 0000000 0000000 {
"access_token":"access_token",
"refresh_token":"refresh_token",
"expires_in":3600
} rack-oauth2-1.21.3/spec/mock_response/tokens/legacy.txt 0000664 0000000 0000000 00000000046 14310224506 0023024 0 ustar 00root root 0000000 0000000 access_token=access_token&expires=3600 rack-oauth2-1.21.3/spec/mock_response/tokens/legacy_without_expires_in.txt 0000664 0000000 0000000 00000000031 14310224506 0027026 0 ustar 00root root 0000000 0000000 access_token=access_token rack-oauth2-1.21.3/spec/mock_response/tokens/mac.json 0000664 0000000 0000000 00000000252 14310224506 0022451 0 ustar 00root root 0000000 0000000 {
"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.21.3/spec/mock_response/tokens/unknown.json 0000664 0000000 0000000 00000000165 14310224506 0023413 0 ustar 00root root 0000000 0000000 {
"access_token":"access_token",
"refresh_token":"refresh_token",
"token_type":"unknown",
"expires_in":3600
} rack-oauth2-1.21.3/spec/rack/ 0000775 0000000 0000000 00000000000 14310224506 0015565 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/ 0000775 0000000 0000000 00000000000 14310224506 0016767 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/access_token/ 0000775 0000000 0000000 00000000000 14310224506 0021430 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/access_token/authenticator_spec.rb 0000664 0000000 0000000 00000002252 14310224506 0025642 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/access_token/bearer_spec.rb 0000664 0000000 0000000 00000001113 14310224506 0024223 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/access_token/legacy_spec.rb 0000664 0000000 0000000 00000001255 14310224506 0024236 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/access_token/mac/ 0000775 0000000 0000000 00000000000 14310224506 0022170 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/access_token/mac/sha256_hex_verifier_spec.rb 0000664 0000000 0000000 00000001504 14310224506 0027276 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/access_token/mac/signature_spec.rb 0000664 0000000 0000000 00000003542 14310224506 0025534 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/access_token/mac/verifier_spec.rb 0000664 0000000 0000000 00000001310 14310224506 0025335 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/access_token/mac_spec.rb 0000664 0000000 0000000 00000011016 14310224506 0023526 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/access_token_spec.rb 0000664 0000000 0000000 00000004234 14310224506 0022772 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/client/ 0000775 0000000 0000000 00000000000 14310224506 0020245 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/client/error_spec.rb 0000664 0000000 0000000 00000000743 14310224506 0022741 0 ustar 00root root 0000000 0000000 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], error[:error_description]].join(' :: ') }
its(:response) { should == error }
end
rack-oauth2-1.21.3/spec/rack/oauth2/client/grant/ 0000775 0000000 0000000 00000000000 14310224506 0021360 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/client/grant/authorization_code_spec.rb 0000664 0000000 0000000 00000001775 14310224506 0026623 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/client/grant/client_credentials_spec.rb 0000664 0000000 0000000 00000000242 14310224506 0026550 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/client/grant/jwt_bearer_spec.rb 0000664 0000000 0000000 00000001064 14310224506 0025044 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/client/grant/password_spec.rb 0000664 0000000 0000000 00000001431 14310224506 0024560 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/client/grant/refresh_token_spec.rb 0000664 0000000 0000000 00000001015 14310224506 0025552 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/client/grant/saml2_bearer_spec.rb 0000664 0000000 0000000 00000001046 14310224506 0025256 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/client_spec.rb 0000664 0000000 0000000 00000042303 14310224506 0021606 0 ustar 00root root 0000000 0000000 require 'spec_helper.rb'
describe Rack::OAuth2::Client do
let(:client_id) { 'client_id' }
let(:client_secret) { 'client_secret' }
let :client do
Rack::OAuth2::Client.new(
identifier: client_id,
secret: client_secret,
host: 'server.example.com',
redirect_uri: 'https://client.example.com/callback',
revocation_endpoint: '/oauth2/revoke'
)
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' }
its(:revocation_endpoint) { should == '/oauth2/revoke' }
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%20code' }
end
context 'when scope is given' do
subject { client.authorization_uri(scope: [:scope1, :scope2]) }
it { should include 'scope=scope1%20scope2' }
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 '*args handling' 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 Basic auth method is used' do
context 'when client_id is a url' do
let(:client_id) { 'https://client.example.com'}
it 'should be encoded in "application/x-www-form-urlencoded"' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
request_header: {
'Authorization' => 'Basic aHR0cHMlM0ElMkYlMkZjbGllbnQuZXhhbXBsZS5jb206Y2xpZW50X3NlY3JldA=='
}
)
client.access_token!
end
end
end
context 'when basic_without_www_form_urlencode method is used' do
context 'when client_id is a url' do
let(:client_id) { 'https://client.example.com'}
it 'should be encoded in "application/x-www-form-urlencoded"' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
request_header: {
'Authorization' => 'Basic aHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb206Y2xpZW50X3NlY3JldA=='
}
)
client.access_token! :basic_without_www_form_urlencode
end
end
end
context 'when jwt_bearer auth method specified' do
context 'when client_secret is given' do
it 'should be JWT bearer client assertion w/ auto-generated HS256-signed JWT assertion' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
client_assertion: /^eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9\..+/, # NOTE: HS256
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
code: 'code',
grant_type: 'authorization_code',
redirect_uri: 'https://client.example.com/callback'
}
)
client.access_token! :jwt_bearer
end
end
context 'when private_key is given' do
context 'when RSA key' do
let :client do
Rack::OAuth2::Client.new(
identifier: 'client_id',
private_key: OpenSSL::PKey::RSA.generate(2048),
host: 'server.example.com',
redirect_uri: 'https://client.example.com/callback'
)
end
it 'should be JWT bearer client assertion w/ auto-generated RS256-signed JWT assertion' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
client_assertion: /^eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9\..+/, # NOTE: RS256
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
code: 'code',
grant_type: 'authorization_code',
redirect_uri: 'https://client.example.com/callback'
}
)
client.access_token! :jwt_bearer
end
end
context 'when EC key' do
let :client do
Rack::OAuth2::Client.new(
identifier: 'client_id',
private_key: OpenSSL::PKey::EC.generate('prime256v1'),
host: 'server.example.com',
redirect_uri: 'https://client.example.com/callback'
)
end
it 'should be JWT bearer client assertion w/ auto-generated ES256-signed JWT assertion' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
client_assertion: /^eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9\..+/, # NOTE: ES256
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
code: 'code',
grant_type: 'authorization_code',
redirect_uri: 'https://client.example.com/callback'
}
)
client.access_token! :jwt_bearer
end
end
end
context 'when client_assertion is explicitly given' do
let :client do
Rack::OAuth2::Client.new(
identifier: 'client_id',
host: 'server.example.com',
redirect_uri: 'https://client.example.com/callback'
)
end
it 'should be JWT bearer client assertion w/ specified assertion' do
mock_response(
:post,
'https://server.example.com/oauth2/token',
'tokens/bearer.json',
params: {
client_assertion: 'any.jwt.assertion',
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
code: 'code',
grant_type: 'authorization_code',
redirect_uri: 'https://client.example.com/callback'
}
)
client.access_token! :jwt_bearer, client_assertion: 'any.jwt.assertion'
end
end
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 }
context 'when token_type is forced' do
before do
client.force_token_type! :bearer
end
it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
its(:token_type) { should == :bearer }
end
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
describe '#revoke!' do
context 'when access_token given' do
before do
mock_response(
:post,
'https://server.example.com/oauth2/revoke',
'blank',
status: 200,
body: {
token: 'access_token',
token_type_hint: 'access_token'
}
)
end
it do
client.revoke!(access_token: 'access_token').should == :success
end
end
context 'when refresh_token given' do
before do
mock_response(
:post,
'https://server.example.com/oauth2/revoke',
'blank',
status: 200,
body: {
token: 'refresh_token',
token_type_hint: 'refresh_token'
}
)
end
context 'as argument' do
it do
client.revoke!(refresh_token: 'refresh_token').should == :success
end
end
context 'as grant' do
it do
client.refresh_token = 'refresh_token'
client.revoke!
end
end
end
context 'when error response given' do
before do
mock_response(
:post,
'https://server.example.com/oauth2/revoke',
'errors/invalid_request.json',
status: 400
)
end
it do
expect do
client.revoke! access_token: 'access_token'
end.to raise_error Rack::OAuth2::Client::Error
end
end
context 'when no token given' do
it do
expect do
client.revoke!
end.to raise_error ArgumentError
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',
revocation_endpoint: '/oauth2/revoke'
)
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
describe '#revoke!' do
it do
expect { client.revoke! access_token: 'access_token' }.to raise_error 'No Host Info'
end
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/debugger/ 0000775 0000000 0000000 00000000000 14310224506 0020553 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/debugger/request_filter_spec.rb 0000664 0000000 0000000 00000002061 14310224506 0025146 0 ustar 00root root 0000000 0000000 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({hello: 'world'}.to_json) }
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.21.3/spec/rack/oauth2/oauth2_spec.rb 0000664 0000000 0000000 00000004130 14310224506 0021526 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/ 0000775 0000000 0000000 00000000000 14310224506 0020275 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/abstract/ 0000775 0000000 0000000 00000000000 14310224506 0022100 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/abstract/error_spec.rb 0000664 0000000 0000000 00000003306 14310224506 0024572 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/authorize/ 0000775 0000000 0000000 00000000000 14310224506 0022307 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/authorize/code_spec.rb 0000664 0000000 0000000 00000003645 14310224506 0024570 0 ustar 00root root 0000000 0000000 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.gsub('+', '%20')}&state=state"
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/server/authorize/error_spec.rb 0000664 0000000 0000000 00000007445 14310224506 0025011 0 ustar 00root root 0000000 0000000 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, headers, response = error.finish
state.should == 302
headers["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, headers, response = error.finish
state.should == 302
headers["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, headers, response = error.finish
state.should == 302
headers["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.21.3/spec/rack/oauth2/server/authorize/extensions/ 0000775 0000000 0000000 00000000000 14310224506 0024506 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/authorize/extensions/code_and_token_spec.rb 0000664 0000000 0000000 00000004333 14310224506 0031004 0 ustar 00root root 0000000 0000000 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.gsub('+', '%20')}"
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/server/authorize/token_spec.rb 0000664 0000000 0000000 00000004620 14310224506 0024770 0 ustar 00root root 0000000 0000000 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.gsub('+', '%20')}&state=state"
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/server/authorize_spec.rb 0000664 0000000 0000000 00000015177 14310224506 0023661 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/extension/ 0000775 0000000 0000000 00000000000 14310224506 0022311 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/extension/pkce_spec.rb 0000664 0000000 0000000 00000012206 14310224506 0024573 0 ustar 00root root 0000000 0000000 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(:code_verifier) { SecureRandom.hex(16) }
let(:code_challenge) { Base64.urlsafe_encode64(OpenSSL::Digest::SHA256.digest(code_verifier)).delete('=') }
let(:code_challenge_method) { :S256 }
subject { @request }
describe 'authorization request' do
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
@request = request
end
end
context 'when code_challenge is given' do
context 'when code_challenge_method is given' do
before do
request.get "/?response_type=code&client_id=client&redirect_uri=#{redirect_uri}&state=state&code_challenge=#{code_challenge}&code_challenge_method=#{code_challenge_method}"
end
its(:code_challenge) { should == code_challenge }
its(:code_challenge_method) { should == code_challenge_method.to_s }
end
context 'when code_challenge_method is omitted' do
before do
request.get "/?response_type=code&client_id=client&redirect_uri=#{redirect_uri}&state=state&code_challenge=#{code_challenge}"
end
its(:code_challenge) { should == code_challenge }
its(:code_challenge_method) { should == nil }
end
end
context 'otherwise' do
before do
request.get "/?response_type=code&client_id=client&redirect_uri=#{redirect_uri}&state=state"
end
its(:code_challenge) { should == nil }
its(:code_challenge_method) { should == nil }
end
end
describe 'token request' do
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
@request = request
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:default_params) do
{
grant_type: 'authorization_code',
client_id: 'client_id',
client_secret: 'client_secret',
code: 'authorization_code',
redirect_uri: 'http://client.example.com/callback'
}
end
context 'when code_verifier is given' do
before do
request.post '/', params: default_params.merge(
code_verifier: code_verifier
)
end
its(:code_verifier) { should == code_verifier }
describe '#verify_code_verifier!' do
context 'when code_verifier is given with code_challenge_method=plain' do
it do
expect do
subject.verify_code_verifier! code_verifier, :plain
end.not_to raise_error
end
end
context 'when collect code_challenge is given' do
it do
expect do
subject.verify_code_verifier! code_challenge
end.not_to raise_error
end
end
context 'when wrong code_challenge is blank' do
it do
expect do
subject.verify_code_verifier! 'wrong'
end.to raise_error Rack::OAuth2::Server::Token::BadRequest, /invalid_grant/
end
end
context 'when code_challenge is nil' do
it do
expect do
subject.verify_code_verifier! nil
end.to raise_error Rack::OAuth2::Server::Token::BadRequest, /invalid_grant/
end
end
context 'when unknown code_challenge_method is given' do
it do
expect do
subject.verify_code_verifier! code_challenge, :unknown
end.to raise_error Rack::OAuth2::Server::Token::BadRequest, /invalid_grant/
end
end
end
end
context 'otherwise' do
before do
request.post '/', params: default_params
end
its(:code_verifier) { should == nil }
describe '#verify_code_verifier!' do
context 'when code_verifier is given with code_challenge_method=plain' do
it do
expect do
subject.verify_code_verifier! code_verifier, :plain
end.to raise_error Rack::OAuth2::Server::Token::BadRequest, /invalid_grant/
end
end
context 'when collect code_challenge is given' do
it do
expect do
subject.verify_code_verifier! code_challenge
end.to raise_error Rack::OAuth2::Server::Token::BadRequest, /invalid_grant/
end
end
context 'when wrong code_challenge is blank' do
it do
expect do
subject.verify_code_verifier! 'wrong'
end.to raise_error Rack::OAuth2::Server::Token::BadRequest, /invalid_grant/
end
end
context 'when code_challenge is nil' do
it do
expect do
subject.verify_code_verifier! nil
end.not_to raise_error
end
end
context 'when unknown code_challenge_method is given' do
it do
expect do
subject.verify_code_verifier! code_challenge, :unknown
end.to raise_error Rack::OAuth2::Server::Token::BadRequest, /invalid_grant/
end
end
end
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/server/extension/response_mode_spec.rb 0000664 0000000 0000000 00000001600 14310224506 0026507 0 ustar 00root root 0000000 0000000 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(:response_mode) { 'form_post' }
subject { @request }
describe 'authorization request' do
let :app do
Rack::OAuth2::Server::Authorize.new do |request, response|
@request = request
end
end
context 'when response_mode is given' do
before do
request.get "/?response_type=code&client_id=client&redirect_uri=#{redirect_uri}&state=state&response_mode=#{response_mode}"
end
its(:response_mode) { should == response_mode }
end
context 'otherwise' do
before do
request.get "/?response_type=code&client_id=client&redirect_uri=#{redirect_uri}&state=state"
end
its(:response_mode) { should == nil }
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/server/resource/ 0000775 0000000 0000000 00000000000 14310224506 0022124 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/resource/bearer/ 0000775 0000000 0000000 00000000000 14310224506 0023364 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/resource/bearer/error_spec.rb 0000664 0000000 0000000 00000003406 14310224506 0026057 0 ustar 00root root 0000000 0000000 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, headers, response = error.finish
headers['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.21.3/spec/rack/oauth2/server/resource/bearer_spec.rb 0000664 0000000 0000000 00000007647 14310224506 0024741 0 ustar 00root root 0000000 0000000 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, headers, 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, headers, response = request
status.should == 401
headers['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, headers, 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, headers, 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, headers, response = request
headers['WWW-Authenticate'].should include "Bearer realm=\"#{realm}\""
end
end
context 'otherwize' do
it 'should use default realm' do
status, headers, response = request
headers['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.21.3/spec/rack/oauth2/server/resource/error_spec.rb 0000664 0000000 0000000 00000012706 14310224506 0024622 0 ustar 00root root 0000000 0000000 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, headers, response = error.finish
status.should == 400
headers['Content-Type'].should == 'application/json'
response.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, headers, response = error_with_scheme.finish
status.should == 401
headers['Content-Type'].should == 'application/json'
headers['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\", error=\"invalid_token\""
response.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, headers, response = error_with_scheme.finish
headers['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
response.first.should include '"error":"something"'
end
end
context 'when no error_code is given' do
let(:error) { Rack::OAuth2::Server::Resource::Unauthorized.new }
it 'should have error_code in body but not in WWW-Authenticate header' do
status, headers, response = error_with_scheme.finish
headers['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
response.first.should == '{"error":"unauthorized"}'
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, headers, response = error_with_scheme.finish
headers['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
response.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, headers, response = error.finish
status.should == 403
headers['Content-Type'].should == 'application/json'
response.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, headers, response = error.finish
response.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.21.3/spec/rack/oauth2/server/resource/mac/ 0000775 0000000 0000000 00000000000 14310224506 0022664 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/resource/mac/error_spec.rb 0000664 0000000 0000000 00000003353 14310224506 0025360 0 ustar 00root root 0000000 0000000 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, headers, response = error.finish
headers['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.21.3/spec/rack/oauth2/server/resource/mac_spec.rb 0000664 0000000 0000000 00000010241 14310224506 0024221 0 ustar 00root root 0000000 0000000 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, headers, 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, headers, 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, headers, response = request
status.should == 401
headers['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, headers, 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, headers, 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, headers, response = request
headers['WWW-Authenticate'].should include "MAC realm=\"#{realm}\""
end
end
context 'otherwize' do
it 'should use default realm' do
status, headers, response = request
headers['WWW-Authenticate'].should include "MAC realm=\"#{Rack::OAuth2::Server::Resource::DEFAULT_REALM}\""
end
end
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/server/resource_spec.rb 0000664 0000000 0000000 00000001153 14310224506 0023463 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/token/ 0000775 0000000 0000000 00000000000 14310224506 0021415 5 ustar 00root root 0000000 0000000 rack-oauth2-1.21.3/spec/rack/oauth2/server/token/authorization_code_spec.rb 0000664 0000000 0000000 00000002505 14310224506 0026650 0 ustar 00root root 0000000 0000000 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.headers['Cache-Control'].should == 'no-store'
response.headers['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.21.3/spec/rack/oauth2/server/token/client_credentials_spec.rb 0000664 0000000 0000000 00000003132 14310224506 0026606 0 ustar 00root root 0000000 0000000 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|
unless request.client_id == client_id && request.client_secret == client_secret
request.invalid_client!
end
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
end
end
let(:client_id) { 'client_id '}
let(:client_secret) { 'client_secret' }
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"' }
context 'basic auth' do
let(:params) do
{ grant_type: 'client_credentials' }
end
let(:encoded_creds) do
Base64.strict_encode64([
Rack::OAuth2::Util.www_form_url_encode(client_id),
Rack::OAuth2::Util.www_form_url_encode(client_secret)
].join(':'))
end
subject do
request.post('/',
{params: params, 'HTTP_AUTHORIZATION' => "Basic #{encoded_creds}"})
end
its(:status) { should == 200 }
context 'compliance with RFC6749 sec 2.3.1' do
let(:client_id) { 'client: yes/please!' }
let(:client_secret) { 'terrible:secret:of:space' }
its(:status) { should == 200 }
end
end
end
rack-oauth2-1.21.3/spec/rack/oauth2/server/token/error_spec.rb 0000664 0000000 0000000 00000005316 14310224506 0024112 0 ustar 00root root 0000000 0000000 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, headers, response = error.finish
status.should == 400
headers['Content-Type'].should == 'application/json'
response.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, headers, response = error.finish
status.should == 401
headers['Content-Type'].should == 'application/json'
headers['WWW-Authenticate'].should == 'Basic realm="OAuth2 Token Endpoint"'
response.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.21.3/spec/rack/oauth2/server/token/jwt_bearer_spec.rb 0000664 0000000 0000000 00000002066 14310224506 0025104 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/token/password_spec.rb 0000664 0000000 0000000 00000002134 14310224506 0024616 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/token/refresh_token_spec.rb 0000664 0000000 0000000 00000002034 14310224506 0025611 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/token/saml2_bearer_spec.rb 0000664 0000000 0000000 00000002060 14310224506 0025310 0 ustar 00root root 0000000 0000000 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.21.3/spec/rack/oauth2/server/token_spec.rb 0000664 0000000 0000000 00000014170 14310224506 0022757 0 ustar 00root root 0000000 0000000 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, headers, response = app.call(env)
status.should == 400
response.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, headers, 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
context 'when client_id is given via JWT client assertion' do
before do
require 'json/jwt'
params[:client_assertion] = JSON::JWT.new(
sub: params[:client_id]
# NOTE: actual client_assertion should have more claims.
).sign('client_secret').to_s
params[:client_assertion_type] = Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER
params.delete(:client_id)
end
context 'when client_assertion is invalid JWT' do
before do
params[:client_assertion] = 'invalid-jwt'
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
context 'when client_assertion_type is missing' do
before do
params.delete(:client_assertion_type)
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
context 'when client_assertion_type is unknown' do
before do
params[:client_assertion_type] = 'unknown'
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
context 'when client_assertion issuer is different from client_id' do
before do
params[:client_id] = 'another_client_id'
end
its(:status) { should == 400 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"error":"invalid_request"' }
end
context 'otherwise' do
its(:status) { should == 200 }
its(:content_type) { should == 'application/json' }
its(:body) { should include '"access_token":"access_token"' }
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}\"" }
if error == :invalid_client
its(:headers) { should include 'WWW-Authenticate' }
end
end
end
context 'when skip_www_authenticate option is specified on invalid_client' do
let(:app) do
Rack::OAuth2::Server::Token.new do |request, response|
request.invalid_client!(
Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION[:invalid_client],
skip_www_authenticate: true
)
end
end
its(:headers) { should_not include 'WWW-Authenticate' }
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.21.3/spec/rack/oauth2/util_spec.rb 0000664 0000000 0000000 00000005062 14310224506 0021306 0 ustar 00root root 0000000 0000000 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 '.www_form_url_encode' do
subject { util.www_form_url_encode '=+ .-/' }
it { should == '%3D%2B+.-%2F' }
end
describe '.www_form_urldecode' do
subject { util.www_form_url_decode '%3D%2B+.-%2F' }
it { should == '=+ .-/' }
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.21.3/spec/spec_helper.rb 0000664 0000000 0000000 00000000605 14310224506 0017464 0 ustar 00root root 0000000 0000000 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