rack-oauth2-revibe 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +20 -0
  8. data/README.rdoc +78 -0
  9. data/Rakefile +25 -0
  10. data/VERSION +1 -0
  11. data/lib/rack/oauth2.rb +67 -0
  12. data/lib/rack/oauth2/access_token.rb +36 -0
  13. data/lib/rack/oauth2/access_token/authenticator.rb +24 -0
  14. data/lib/rack/oauth2/access_token/bearer.rb +11 -0
  15. data/lib/rack/oauth2/access_token/legacy.rb +23 -0
  16. data/lib/rack/oauth2/access_token/mac.rb +103 -0
  17. data/lib/rack/oauth2/access_token/mac/sha256_hex_verifier.rb +17 -0
  18. data/lib/rack/oauth2/access_token/mac/signature.rb +34 -0
  19. data/lib/rack/oauth2/access_token/mac/verifier.rb +44 -0
  20. data/lib/rack/oauth2/client.rb +139 -0
  21. data/lib/rack/oauth2/client/error.rb +14 -0
  22. data/lib/rack/oauth2/client/grant.rb +30 -0
  23. data/lib/rack/oauth2/client/grant/authorization_code.rb +12 -0
  24. data/lib/rack/oauth2/client/grant/client_credentials.rb +10 -0
  25. data/lib/rack/oauth2/client/grant/facebook_token.rb +12 -0
  26. data/lib/rack/oauth2/client/grant/password.rb +11 -0
  27. data/lib/rack/oauth2/client/grant/refresh_token.rb +11 -0
  28. data/lib/rack/oauth2/debugger.rb +3 -0
  29. data/lib/rack/oauth2/debugger/request_filter.rb +30 -0
  30. data/lib/rack/oauth2/server.rb +4 -0
  31. data/lib/rack/oauth2/server/abstract.rb +4 -0
  32. data/lib/rack/oauth2/server/abstract/error.rb +69 -0
  33. data/lib/rack/oauth2/server/abstract/handler.rb +20 -0
  34. data/lib/rack/oauth2/server/abstract/request.rb +29 -0
  35. data/lib/rack/oauth2/server/abstract/response.rb +15 -0
  36. data/lib/rack/oauth2/server/authorize.rb +117 -0
  37. data/lib/rack/oauth2/server/authorize/code.rb +39 -0
  38. data/lib/rack/oauth2/server/authorize/error.rb +71 -0
  39. data/lib/rack/oauth2/server/authorize/extension.rb +12 -0
  40. data/lib/rack/oauth2/server/authorize/extension/code_and_token.rb +39 -0
  41. data/lib/rack/oauth2/server/authorize/token.rb +43 -0
  42. data/lib/rack/oauth2/server/resource.rb +55 -0
  43. data/lib/rack/oauth2/server/resource/bearer.rb +47 -0
  44. data/lib/rack/oauth2/server/resource/bearer/error.rb +24 -0
  45. data/lib/rack/oauth2/server/resource/error.rb +81 -0
  46. data/lib/rack/oauth2/server/resource/mac.rb +36 -0
  47. data/lib/rack/oauth2/server/resource/mac/error.rb +24 -0
  48. data/lib/rack/oauth2/server/token.rb +87 -0
  49. data/lib/rack/oauth2/server/token/authorization_code.rb +28 -0
  50. data/lib/rack/oauth2/server/token/client_credentials.rb +23 -0
  51. data/lib/rack/oauth2/server/token/error.rb +54 -0
  52. data/lib/rack/oauth2/server/token/extension.rb +12 -0
  53. data/lib/rack/oauth2/server/token/extension/jwt.rb +37 -0
  54. data/lib/rack/oauth2/server/token/facebook_token.rb +27 -0
  55. data/lib/rack/oauth2/server/token/password.rb +27 -0
  56. data/lib/rack/oauth2/server/token/refresh_token.rb +26 -0
  57. data/lib/rack/oauth2/util.rb +58 -0
  58. data/rack-oauth2.gemspec +30 -0
  59. data/spec/helpers/time.rb +19 -0
  60. data/spec/helpers/webmock_helper.rb +41 -0
  61. data/spec/mock_response/blank +0 -0
  62. data/spec/mock_response/errors/invalid_request.json +4 -0
  63. data/spec/mock_response/resources/fake.txt +1 -0
  64. data/spec/mock_response/tokens/_Bearer.json +6 -0
  65. data/spec/mock_response/tokens/bearer.json +6 -0
  66. data/spec/mock_response/tokens/legacy.json +5 -0
  67. data/spec/mock_response/tokens/legacy.txt +1 -0
  68. data/spec/mock_response/tokens/legacy_without_expires_in.txt +1 -0
  69. data/spec/mock_response/tokens/mac.json +8 -0
  70. data/spec/mock_response/tokens/unknown.json +6 -0
  71. data/spec/rack/oauth2/access_token/authenticator_spec.rb +43 -0
  72. data/spec/rack/oauth2/access_token/bearer_spec.rb +18 -0
  73. data/spec/rack/oauth2/access_token/legacy_spec.rb +23 -0
  74. data/spec/rack/oauth2/access_token/mac/sha256_hex_verifier_spec.rb +28 -0
  75. data/spec/rack/oauth2/access_token/mac/signature_spec.rb +59 -0
  76. data/spec/rack/oauth2/access_token/mac/verifier_spec.rb +25 -0
  77. data/spec/rack/oauth2/access_token/mac_spec.rb +141 -0
  78. data/spec/rack/oauth2/access_token_spec.rb +69 -0
  79. data/spec/rack/oauth2/client/error_spec.rb +18 -0
  80. data/spec/rack/oauth2/client/grant/authorization_code_spec.rb +37 -0
  81. data/spec/rack/oauth2/client/grant/client_credentials_spec.rb +7 -0
  82. data/spec/rack/oauth2/client/grant/password_spec.rb +33 -0
  83. data/spec/rack/oauth2/client/grant/refresh_token_spec.rb +21 -0
  84. data/spec/rack/oauth2/client_spec.rb +287 -0
  85. data/spec/rack/oauth2/debugger/request_filter_spec.rb +33 -0
  86. data/spec/rack/oauth2/oauth2_spec.rb +74 -0
  87. data/spec/rack/oauth2/server/abstract/error_spec.rb +59 -0
  88. data/spec/rack/oauth2/server/authorize/code_spec.rb +57 -0
  89. data/spec/rack/oauth2/server/authorize/error_spec.rb +103 -0
  90. data/spec/rack/oauth2/server/authorize/extensions/code_and_token_spec.rb +60 -0
  91. data/spec/rack/oauth2/server/authorize/token_spec.rb +73 -0
  92. data/spec/rack/oauth2/server/authorize_spec.rb +214 -0
  93. data/spec/rack/oauth2/server/resource/bearer/error_spec.rb +52 -0
  94. data/spec/rack/oauth2/server/resource/bearer_spec.rb +123 -0
  95. data/spec/rack/oauth2/server/resource/error_spec.rb +147 -0
  96. data/spec/rack/oauth2/server/resource/mac/error_spec.rb +52 -0
  97. data/spec/rack/oauth2/server/resource/mac_spec.rb +119 -0
  98. data/spec/rack/oauth2/server/resource_spec.rb +23 -0
  99. data/spec/rack/oauth2/server/token/authorization_code_spec.rb +43 -0
  100. data/spec/rack/oauth2/server/token/client_credentials_spec.rb +23 -0
  101. data/spec/rack/oauth2/server/token/error_spec.rb +77 -0
  102. data/spec/rack/oauth2/server/token/password_spec.rb +37 -0
  103. data/spec/rack/oauth2/server/token/refresh_token_spec.rb +34 -0
  104. data/spec/rack/oauth2/server/token_spec.rb +134 -0
  105. data/spec/rack/oauth2/util_spec.rb +97 -0
  106. data/spec/spec_helper.rb +14 -0
  107. metadata +326 -0
@@ -0,0 +1,27 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Token
5
+ class FacebookToken < Abstract::Handler
6
+ def call(env)
7
+ @request = Request.new(env)
8
+ @response = Response.new(request)
9
+ super
10
+ end
11
+
12
+ class Request < Token::Request
13
+ attr_required :facebook_token
14
+
15
+ def initialize(env)
16
+ super
17
+ @grant_type = :facebook_token
18
+ @facebook_token = params['facebook_token']
19
+ attr_missing!
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,27 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Token
5
+ class Password < Abstract::Handler
6
+ def call(env)
7
+ @request = Request.new(env)
8
+ @response = Response.new(request)
9
+ super
10
+ end
11
+
12
+ class Request < Token::Request
13
+ attr_required :username, :password
14
+
15
+ def initialize(env)
16
+ super
17
+ @grant_type = :password
18
+ @username = params['username']
19
+ @password = params['password']
20
+ attr_missing!
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Token
5
+ class RefreshToken < Abstract::Handler
6
+ def call(env)
7
+ @request = Request.new(env)
8
+ @response = Response.new(request)
9
+ super
10
+ end
11
+
12
+ class Request < Token::Request
13
+ attr_required :refresh_token
14
+
15
+ def initialize(env)
16
+ super
17
+ @grant_type = :refresh_token
18
+ @refresh_token = params['refresh_token']
19
+ attr_missing!
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,58 @@
1
+ require 'base64'
2
+
3
+ module Rack
4
+ module OAuth2
5
+ module Util
6
+ class << self
7
+ def rfc3986_encode(text)
8
+ URI.encode(text, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
9
+ end
10
+
11
+ def base64_encode(text)
12
+ Base64.encode64(text).gsub(/\n/, '')
13
+ end
14
+
15
+ def compact_hash(hash)
16
+ hash.reject do |key, value|
17
+ value.blank?
18
+ end
19
+ end
20
+
21
+ def parse_uri(uri)
22
+ case uri
23
+ when URI::Generic
24
+ uri
25
+ when String
26
+ URI.parse(uri)
27
+ else
28
+ raise "Invalid format of URI is given."
29
+ end
30
+ end
31
+
32
+ def redirect_uri(base_uri, location, params)
33
+ redirect_uri = parse_uri base_uri
34
+ case location
35
+ when :query
36
+ redirect_uri.query = [redirect_uri.query, Util.compact_hash(params).to_query].compact.join('&')
37
+ when :fragment
38
+ redirect_uri.fragment = Util.compact_hash(params).to_query
39
+ end
40
+ redirect_uri.to_s
41
+ end
42
+
43
+ def uri_match?(base, given)
44
+ base = parse_uri(base)
45
+ given = parse_uri(given)
46
+ base.path = '/' if base.path.blank?
47
+ given.path = '/' if given.path.blank?
48
+ [:scheme, :host, :port].all? do |key|
49
+ base.send(key) == given.send(key)
50
+ end && /^#{base.path}/ =~ given.path
51
+ rescue
52
+ false
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "rack-oauth2-revibe"
3
+ s.version = File.read("VERSION")
4
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
5
+ s.authors = ["nov matake"]
6
+ s.description = %q{OAuth 2.0 Server & Client Library. Both Bearer and MAC token type are supported.}
7
+ s.summary = %q{OAuth 2.0 Server & Client Library - Both Bearer and MAC token type are supported}
8
+ s.email = "nov@matake.jp"
9
+ s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
10
+ s.rdoc_options = ["--charset=UTF-8"]
11
+ s.homepage = "http://github.com/nov/rack-oauth2"
12
+ s.license = 'MIT'
13
+ s.require_paths = ["lib"]
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.add_runtime_dependency "rack", ">= 1.1"
18
+ s.add_runtime_dependency "multi_json", ">= 1.3.6"
19
+ s.add_runtime_dependency "httpclient", ">= 2.2.0.2"
20
+ s.add_runtime_dependency "activesupport", ">= 2.3"
21
+ s.add_runtime_dependency "attr_required", ">= 0.0.5"
22
+ s.add_development_dependency "rake", ">= 0.8"
23
+ if RUBY_VERSION >= '1.9'
24
+ s.add_development_dependency "cover_me", ">= 1.2.0"
25
+ else
26
+ s.add_development_dependency "rcov", ">= 0.9"
27
+ end
28
+ s.add_development_dependency "rspec", ">= 2"
29
+ s.add_development_dependency "webmock", ">= 1.6.2"
30
+ end
@@ -0,0 +1,19 @@
1
+ class Time
2
+ class << self
3
+ def now_with_fixed_time
4
+ if @fixed_time
5
+ @fixed_time.dup
6
+ else
7
+ now_without_fixed_time
8
+ end
9
+ end
10
+ alias_method_chain :now, :fixed_time
11
+
12
+ def fix(time = Time.now)
13
+ @fixed_time = time
14
+ yield
15
+ ensure
16
+ @fixed_time = nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ require 'webmock/rspec'
2
+
3
+ module WebMockHelper
4
+ def mock_response(method, endpoint, response_file, options = {})
5
+ stub_request(method, endpoint).with(
6
+ request_for(method, options)
7
+ ).to_return(
8
+ response_for(response_file, options)
9
+ )
10
+ end
11
+
12
+ private
13
+
14
+ def request_for(method, options = {})
15
+ request = {}
16
+ if options[:params]
17
+ case method
18
+ when :post, :put
19
+ request[:body] = options[:params]
20
+ else
21
+ request[:query] = options[:params]
22
+ end
23
+ end
24
+ if options[:request_header]
25
+ request[:headers] = options[:request_header]
26
+ end
27
+ request
28
+ end
29
+
30
+ def response_for(response_file, options = {})
31
+ response = {}
32
+ response[:body] = File.new(File.join(File.dirname(__FILE__), '../mock_response', response_file))
33
+ if options[:status]
34
+ response[:status] = options[:status]
35
+ end
36
+ response
37
+ end
38
+ end
39
+
40
+ include WebMockHelper
41
+ WebMock.disable_net_connect!
File without changes
@@ -0,0 +1,4 @@
1
+ {
2
+ "error":"invalid_request",
3
+ "error_description":"error description"
4
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "access_token":"access_token",
3
+ "refresh_token":"refresh_token",
4
+ "token_type":"Bearer",
5
+ "expires_in":3600
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "access_token":"access_token",
3
+ "refresh_token":"refresh_token",
4
+ "token_type":"bearer",
5
+ "expires_in":3600
6
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "access_token":"access_token",
3
+ "refresh_token":"refresh_token",
4
+ "expires_in":3600
5
+ }
@@ -0,0 +1 @@
1
+ access_token=access_token&expires=3600
@@ -0,0 +1 @@
1
+ access_token=access_token
@@ -0,0 +1,8 @@
1
+ {
2
+ "token_type":"mac",
3
+ "mac_algorithm":"hmac-sha-256",
4
+ "expires_in":3600,
5
+ "mac_key":"secret",
6
+ "refresh_token":"refresh_token",
7
+ "access_token":"access_token"
8
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "access_token":"access_token",
3
+ "refresh_token":"refresh_token",
4
+ "token_type":"unknown",
5
+ "expires_in":3600
6
+ }
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken::Authenticator do
4
+ let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
5
+ let(:request) { HTTP::Message.new_request(:get, URI.parse(resource_endpoint)) }
6
+ let(:authenticator) { Rack::OAuth2::AccessToken::Authenticator.new(token) }
7
+
8
+ shared_examples_for :authenticator do
9
+ it 'should let the token authenticate the request' do
10
+ token.should_receive(:authenticate).with(request)
11
+ authenticator.filter_request(request)
12
+ end
13
+ end
14
+
15
+ context 'when Legacy token is given' do
16
+ let(:token) do
17
+ Rack::OAuth2::AccessToken::Legacy.new(
18
+ :access_token => 'access_token'
19
+ )
20
+ end
21
+ it_behaves_like :authenticator
22
+ end
23
+
24
+ context 'when Bearer token is given' do
25
+ let(:token) do
26
+ Rack::OAuth2::AccessToken::Bearer.new(
27
+ :access_token => 'access_token'
28
+ )
29
+ end
30
+ it_behaves_like :authenticator
31
+ end
32
+
33
+ context 'when MAC token is given' do
34
+ let(:token) do
35
+ Rack::OAuth2::AccessToken::MAC.new(
36
+ :access_token => 'access_token',
37
+ :mac_key => 'secret',
38
+ :mac_algorithm => 'hmac-sha-256'
39
+ )
40
+ end
41
+ it_behaves_like :authenticator
42
+ end
43
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken::Bearer do
4
+ let :token do
5
+ Rack::OAuth2::AccessToken::Bearer.new(
6
+ :access_token => 'access_token'
7
+ )
8
+ end
9
+ let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
10
+ let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {:hello => "world"}, {}) }
11
+
12
+ describe '.authenticate' do
13
+ it 'should set Authorization header' do
14
+ request.header.should_receive(:[]=).with('Authorization', 'Bearer access_token')
15
+ token.authenticate(request)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken::Legacy do
4
+ let :token do
5
+ Rack::OAuth2::AccessToken::Legacy.new(
6
+ :access_token => 'access_token'
7
+ )
8
+ end
9
+ let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
10
+ let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {:hello => "world"}, {}) }
11
+
12
+ describe '#to_s' do
13
+ subject { token }
14
+ its(:to_s) { should == token.access_token }
15
+ end
16
+
17
+ describe '.authenticate' do
18
+ it 'should set Authorization header' do
19
+ request.header.should_receive(:[]=).with('Authorization', 'OAuth access_token')
20
+ token.authenticate(request)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier do
4
+
5
+ # From the example of webtopay wallet API spec
6
+ # ref) https://www.webtopay.com/wallet/#authentication
7
+ context 'when example from webtopay wallet API' do
8
+ subject do
9
+ Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier.new(
10
+ :algorithm => 'hmac-sha-256',
11
+ :raw_body => 'grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=http%3A%2F%2Flocalhost%2Fabc'
12
+ )
13
+ end
14
+ its(:calculate) { should == '21fb73c40b589622d0c78e9cd8900f89d9472aa724d0e5c3eca9ac1cd9d2a6d5' }
15
+ end
16
+
17
+
18
+ context 'when raw_body is empty' do
19
+ subject do
20
+ Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier.new(
21
+ :algorithm => 'hmac-sha-256',
22
+ :raw_body => ''
23
+ )
24
+ end
25
+ its(:calculate) { should be_nil }
26
+ end
27
+
28
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken::MAC::Signature do
4
+ # From the example of Webtopay wallet API
5
+ # ref) https://www.webtopay.com/wallet/
6
+ context 'when ext is not given' do
7
+ subject do
8
+ Rack::OAuth2::AccessToken::MAC::Signature.new(
9
+ :secret => 'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU',
10
+ :algorithm => 'hmac-sha-256',
11
+ :nonce => 'dj83hs9s',
12
+ :ts => 1336363200,
13
+ :method => 'GET',
14
+ :request_uri => '/wallet/rest/api/v1/payment/123',
15
+ :host => 'www.webtopay.com',
16
+ :port => 443
17
+ )
18
+ end
19
+ its(:calculate) { should == 'OZE9fTk2qiRtL1jb01L8lRxC66PTiAGhMDEmboeVeLs=' }
20
+ end
21
+
22
+ # From the example of MAC spec section 1.1
23
+ # ref) http://tools.ietf.org/pdf/draft-ietf-oauth-v2-http-mac-01.pdf
24
+ context 'when ext is not given' do
25
+ subject do
26
+ Rack::OAuth2::AccessToken::MAC::Signature.new(
27
+ :secret => '489dks293j39',
28
+ :algorithm => 'hmac-sha-1',
29
+ :nonce => 'dj83hs9s',
30
+ :ts => 1336363200,
31
+ :method => 'GET',
32
+ :request_uri => '/resource/1?b=1&a=2',
33
+ :host => 'example.com',
34
+ :port => 80
35
+ )
36
+ end
37
+ its(:calculate) { should == '6T3zZzy2Emppni6bzL7kdRxUWL4=' }
38
+ end
39
+
40
+ # From the example of MAC spec section 3.2
41
+ # ref) http://tools.ietf.org/pdf/draft-ietf-oauth-v2-http-mac-01.pdf
42
+ context 'otherwise' do
43
+ subject do
44
+ Rack::OAuth2::AccessToken::MAC::Signature.new(
45
+ :secret => '489dks293j39',
46
+ :algorithm => 'hmac-sha-1',
47
+ :nonce => '7d8f3e4a',
48
+ :ts => 264095,
49
+ :method => 'POST',
50
+ :request_uri => '/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b&c2&a3=2+q',
51
+ :host => 'example.com',
52
+ :port => 80,
53
+ :ext => 'a,b,c'
54
+ )
55
+ end
56
+ its(:calculate) { should == '+txL5oOFHGYjrfdNYH5VEzROaBY=' }
57
+ end
58
+
59
+ end