rack-oauth2-revibe 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
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'