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,20 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ module Abstract
5
+ class Handler
6
+ attr_accessor :authenticator, :request, :response
7
+
8
+ def initialize(&authenticator)
9
+ @authenticator = authenticator
10
+ end
11
+
12
+ def call(env)
13
+ @authenticator.call(@request, @response) if @authenticator
14
+ @response
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ module Abstract
5
+ class Request < Rack::Request
6
+ include AttrRequired, AttrOptional
7
+ attr_required :client_id
8
+ attr_optional :scope
9
+
10
+ def initialize(env)
11
+ super
12
+ @client_id ||= params['client_id']
13
+ @scope = Array(params['scope'].to_s.split(' '))
14
+ end
15
+
16
+ def attr_missing_with_error_handling!
17
+ if params['client_id'].present? && @client_id != params['client_id']
18
+ invalid_request! 'Multiple client credentials are provided.'
19
+ end
20
+ attr_missing_without_error_handling!
21
+ rescue AttrRequired::AttrMissing => e
22
+ invalid_request! e.message, :state => @state, :redirect_uri => @redirect_uri
23
+ end
24
+ alias_method_chain :attr_missing!, :error_handling
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ module Abstract
5
+ class Response < Rack::Response
6
+ include AttrRequired, AttrOptional
7
+
8
+ def initialize(request)
9
+ super([], 200, {})
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,117 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Authorize < Abstract::Handler
5
+ def call(env)
6
+ request = Request.new(env)
7
+ response_type_for(request).new(&@authenticator).call(env).finish
8
+ rescue Rack::OAuth2::Server::Abstract::Error => e
9
+ e.finish
10
+ end
11
+
12
+ private
13
+
14
+ def response_type_for(request)
15
+ response_type = request.params['response_type'].to_s
16
+ case response_type
17
+ when 'code'
18
+ Code
19
+ when 'token'
20
+ Token
21
+ when ''
22
+ request.attr_missing!
23
+ else
24
+ extensions.detect do |extension|
25
+ extension.response_type_for? response_type
26
+ end || request.unsupported_response_type!
27
+ end
28
+ end
29
+
30
+ def extensions
31
+ Extension.constants.sort.collect do |key|
32
+ Extension.const_get key
33
+ end
34
+ end
35
+
36
+ class Request < Abstract::Request
37
+ attr_required :response_type
38
+ attr_optional :redirect_uri, :state
39
+ attr_accessor :verified_redirect_uri
40
+
41
+ def initialize(env)
42
+ super
43
+ # NOTE: Raise before redirect_uri is saved not to redirect back to unverified redirect_uri.
44
+ bad_request! if client_id.blank?
45
+ @redirect_uri = Util.parse_uri(params['redirect_uri']) if params['redirect_uri']
46
+ @state = params['state']
47
+ end
48
+
49
+ def verify_redirect_uri!(pre_registered, allow_partial_match = false)
50
+ @verified_redirect_uri = if redirect_uri.present?
51
+ verified = Array(pre_registered).any? do |_pre_registered_|
52
+ if allow_partial_match
53
+ Util.uri_match?(_pre_registered_, redirect_uri)
54
+ else
55
+ _pre_registered_.to_s == redirect_uri.to_s
56
+ end
57
+ end
58
+ if verified
59
+ redirect_uri
60
+ else
61
+ bad_request!
62
+ end
63
+ elsif pre_registered.present? && Array(pre_registered).size == 1 && !allow_partial_match
64
+ Array(pre_registered).first
65
+ else
66
+ bad_request!
67
+ end
68
+ self.verified_redirect_uri.to_s
69
+ end
70
+
71
+ def error_params_location
72
+ nil # => All errors are raised immediately and no error response are returned to client.
73
+ end
74
+ end
75
+
76
+ class Response < Abstract::Response
77
+ attr_required :redirect_uri
78
+ attr_optional :state, :approval
79
+
80
+ def initialize(request)
81
+ @state = request.state
82
+ super
83
+ end
84
+
85
+ def approved?
86
+ @approval
87
+ end
88
+
89
+ def approve!
90
+ @approval = true
91
+ end
92
+
93
+ def protocol_params
94
+ {:state => state}
95
+ end
96
+
97
+ def redirect_uri_with_credentials
98
+ Util.redirect_uri(redirect_uri, protocol_params_location, protocol_params)
99
+ end
100
+
101
+ def finish
102
+ if approved?
103
+ attr_missing!
104
+ redirect redirect_uri_with_credentials
105
+ end
106
+ super
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ require 'rack/oauth2/server/authorize/code'
115
+ require 'rack/oauth2/server/authorize/token'
116
+ require 'rack/oauth2/server/authorize/extension'
117
+ require 'rack/oauth2/server/authorize/error'
@@ -0,0 +1,39 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Authorize
5
+ class Code < Abstract::Handler
6
+ def call(env)
7
+ @request = Request.new env
8
+ @response = Response.new request
9
+ super
10
+ end
11
+
12
+ class Request < Authorize::Request
13
+ def initialize(env)
14
+ super
15
+ @response_type = :code
16
+ attr_missing!
17
+ end
18
+
19
+ def error_params_location
20
+ :query
21
+ end
22
+ end
23
+
24
+ class Response < Authorize::Response
25
+ attr_required :code
26
+
27
+ def protocol_params
28
+ super.merge(:code => code)
29
+ end
30
+
31
+ def protocol_params_location
32
+ :query
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,71 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Authorize
5
+ module ErrorHandler
6
+ def self.included(klass)
7
+ klass.send :attr_accessor, :redirect_uri, :state, :protocol_params_location
8
+ end
9
+
10
+ def protocol_params
11
+ super.merge(:state => state)
12
+ end
13
+
14
+ def finish
15
+ if redirect_uri.present? && protocol_params_location.present?
16
+ super do |response|
17
+ response.redirect Util.redirect_uri(redirect_uri, protocol_params_location, protocol_params)
18
+ end
19
+ else
20
+ raise self
21
+ end
22
+ end
23
+ end
24
+
25
+ class BadRequest < Abstract::BadRequest
26
+ include ErrorHandler
27
+ end
28
+
29
+ class ServerError < Abstract::ServerError
30
+ include ErrorHandler
31
+ end
32
+
33
+ class TemporarilyUnavailable < Abstract::TemporarilyUnavailable
34
+ include ErrorHandler
35
+ end
36
+
37
+ module ErrorMethods
38
+ DEFAULT_DESCRIPTION = {
39
+ :invalid_request => "The request is missing a required parameter, includes an unsupported parameter or parameter value, or is otherwise malformed.",
40
+ :unauthorized_client => "The client is not authorized to use the requested response type.",
41
+ :access_denied => "The end-user or authorization server denied the request.",
42
+ :unsupported_response_type => "The requested response type is not supported by the authorization server.",
43
+ :invalid_scope => "The requested scope is invalid, unknown, or malformed.",
44
+ :server_error => "Internal Server Error",
45
+ :temporarily_unavailable => "Service Unavailable"
46
+ }
47
+
48
+ def self.included(klass)
49
+ DEFAULT_DESCRIPTION.each do |error, default_description|
50
+ klass.class_eval <<-ERROR
51
+ def #{error}!(description = "#{default_description}", options = {})
52
+ bad_request! :#{error}, description, options
53
+ end
54
+ ERROR
55
+ end
56
+ end
57
+
58
+ def bad_request!(error = :bad_request, description = nil, options = {})
59
+ exception = BadRequest.new error, description, options
60
+ exception.protocol_params_location = error_params_location
61
+ exception.state = state
62
+ exception.redirect_uri = verified_redirect_uri
63
+ raise exception
64
+ end
65
+ end
66
+
67
+ Request.send :include, ErrorMethods
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,12 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Authorize
5
+ module Extension
6
+ # Define your extension in this namespace and load it explicitly.
7
+ # extension/code_and_token.rb would be good example for you.
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Authorize
5
+ module Extension
6
+ class CodeAndToken < Abstract::Handler
7
+ class << self
8
+ def response_type_for?(response_type)
9
+ response_type.split.sort == ['code', 'token']
10
+ end
11
+ end
12
+
13
+ def call(env)
14
+ @request = Request.new env
15
+ @response = Response.new request
16
+ super
17
+ end
18
+
19
+ class Request < Authorize::Token::Request
20
+ def initialize(env)
21
+ super
22
+ @response_type = [:code, :token]
23
+ attr_missing!
24
+ end
25
+ end
26
+
27
+ class Response < Authorize::Token::Response
28
+ attr_required :code
29
+
30
+ def protocol_params
31
+ super.merge(:code => code)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,43 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Authorize
5
+ class Token < Abstract::Handler
6
+ def call(env)
7
+ @request = Request.new env
8
+ @response = Response.new request
9
+ super
10
+ end
11
+
12
+ class Request < Authorize::Request
13
+ def initialize(env)
14
+ super
15
+ @response_type = :token
16
+ attr_missing!
17
+ end
18
+
19
+ def error_params_location
20
+ :fragment
21
+ end
22
+ end
23
+
24
+ class Response < Authorize::Response
25
+ attr_required :access_token
26
+
27
+ def protocol_params
28
+ super.merge(
29
+ access_token.token_response.delete_if do |k, v|
30
+ k == :refresh_token
31
+ end
32
+ )
33
+ end
34
+
35
+ def protocol_params_location
36
+ :fragment
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Resource < Abstract::Handler
5
+ ACCESS_TOKEN = 'rack.oauth2.access_token'
6
+ DEFAULT_REALM = 'Protected by OAuth 2.0'
7
+ attr_accessor :realm, :request
8
+
9
+ def initialize(app, realm = nil, &authenticator)
10
+ @app = app
11
+ @realm = realm
12
+ super &authenticator
13
+ end
14
+
15
+ def call(env)
16
+ if request.oauth2?
17
+ access_token = authenticate! request.setup!
18
+ env[ACCESS_TOKEN] = access_token
19
+ end
20
+ @app.call(env)
21
+ rescue Rack::OAuth2::Server::Abstract::Error => e
22
+ e.realm ||= realm
23
+ e.finish
24
+ end
25
+
26
+ private
27
+
28
+ def authenticate!(request)
29
+ @authenticator.call(request)
30
+ end
31
+
32
+ class Request < Rack::Request
33
+ attr_reader :access_token
34
+
35
+ def initialize(env)
36
+ @env = env
37
+ @auth_header = Rack::Auth::AbstractRequest.new(env)
38
+ end
39
+
40
+ def setup!
41
+ raise 'Define me!'
42
+ end
43
+
44
+ def oauth2?
45
+ raise 'Define me!'
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ require 'rack/oauth2/server/resource/error'
54
+ require 'rack/oauth2/server/resource/bearer'
55
+ require 'rack/oauth2/server/resource/mac'