rack-oauth2 0.2.3 → 0.3.0.alpha

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 (52) hide show
  1. data/Gemfile +1 -0
  2. data/README.rdoc +1 -0
  3. data/VERSION +1 -1
  4. data/lib/rack/oauth2.rb +1 -7
  5. data/lib/rack/oauth2/server.rb +0 -1
  6. data/lib/rack/oauth2/server/abstract.rb +2 -1
  7. data/lib/rack/oauth2/server/abstract/error.rb +55 -0
  8. data/lib/rack/oauth2/server/abstract/handler.rb +2 -3
  9. data/lib/rack/oauth2/server/abstract/request.rb +2 -3
  10. data/lib/rack/oauth2/server/abstract/response.rb +0 -5
  11. data/lib/rack/oauth2/server/authorize.rb +19 -14
  12. data/lib/rack/oauth2/server/authorize/code.rb +8 -19
  13. data/lib/rack/oauth2/server/authorize/error.rb +60 -0
  14. data/lib/rack/oauth2/server/authorize/token.rb +15 -24
  15. data/lib/rack/oauth2/server/resource.rb +1 -79
  16. data/lib/rack/oauth2/server/resource/bearer.rb +74 -0
  17. data/lib/rack/oauth2/server/resource/bearer/error.rb +80 -0
  18. data/lib/rack/oauth2/server/token.rb +12 -19
  19. data/lib/rack/oauth2/server/token/authorization_code.rb +4 -5
  20. data/lib/rack/oauth2/server/token/error.rb +54 -0
  21. data/lib/rack/oauth2/server/token/password.rb +0 -2
  22. data/lib/rack/oauth2/server/token/refresh_token.rb +1 -1
  23. data/lib/rack/oauth2/server/util.rb +29 -0
  24. data/rack-oauth2.gemspec +1 -1
  25. data/spec/rack/oauth2/server/abstract/error_spec.rb +51 -0
  26. data/spec/rack/oauth2/server/authorize/code_spec.rb +42 -28
  27. data/spec/rack/oauth2/server/authorize/error_spec.rb +103 -0
  28. data/spec/rack/oauth2/server/authorize/token_spec.rb +55 -26
  29. data/spec/rack/oauth2/server/authorize_spec.rb +24 -68
  30. data/spec/rack/oauth2/server/resource/bearer/error_spec.rb +118 -0
  31. data/spec/rack/oauth2/server/resource/bearer_spec.rb +117 -0
  32. data/spec/rack/oauth2/server/token/authorization_code_spec.rb +26 -109
  33. data/spec/rack/oauth2/server/token/error_spec.rb +77 -0
  34. data/spec/rack/oauth2/server/token/password_spec.rb +27 -47
  35. data/spec/rack/oauth2/server/token/refresh_token_spec.rb +22 -43
  36. data/spec/rack/oauth2/server/token_spec.rb +77 -116
  37. data/spec/rack/oauth2/server/util_spec.rb +75 -16
  38. data/spec/spec_helper.rb +0 -12
  39. metadata +25 -29
  40. data/lib/rack/oauth2/server/authorize/code_and_token.rb +0 -62
  41. data/lib/rack/oauth2/server/error.rb +0 -73
  42. data/lib/rack/oauth2/server/error/authorize.rb +0 -54
  43. data/lib/rack/oauth2/server/error/resource.rb +0 -50
  44. data/lib/rack/oauth2/server/error/token.rb +0 -59
  45. data/lib/rack/oauth2/server/token/assertion.rb +0 -29
  46. data/spec/rack/oauth2/server/authorize/code_and_token_spec.rb +0 -53
  47. data/spec/rack/oauth2/server/error/authorize_spec.rb +0 -102
  48. data/spec/rack/oauth2/server/error/resource_spec.rb +0 -69
  49. data/spec/rack/oauth2/server/error/token_spec.rb +0 -115
  50. data/spec/rack/oauth2/server/error_spec.rb +0 -107
  51. data/spec/rack/oauth2/server/resource_spec.rb +0 -141
  52. data/spec/rack/oauth2/server/token/assertion_spec.rb +0 -56
data/Gemfile CHANGED
@@ -1 +1,2 @@
1
+ source 'http://rubygems.org'
1
2
  gemspec
data/README.rdoc CHANGED
@@ -14,6 +14,7 @@ http://tools.ietf.org/html/draft-ietf-oauth-v2-10
14
14
  * View RDoc on RDoc.info (http://rdoc.info/github/nov/rack-oauth2)
15
15
  * View Source on GitHub (http://github.com/nov/rack-oauth2)
16
16
  * Report Issues on GitHub (http://github.com/nov/rack-oauth2/issues)
17
+ * Facebook Page (http://www.facebook.com/pages/RackOAuth2/141477809244105)
17
18
 
18
19
  == Usage
19
20
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.3.0.alpha
data/lib/rack/oauth2.rb CHANGED
@@ -3,10 +3,4 @@ require 'json'
3
3
  require 'active_support/core_ext'
4
4
  require 'attr_required'
5
5
  require 'attr_optional'
6
- require 'rack/oauth2/server'
7
-
8
- module Rack
9
- module OAuth2
10
- ACCESS_TOKEN = "rack.oauth2.oauth_token"
11
- end
12
- end
6
+ require 'rack/oauth2/server'
@@ -1,5 +1,4 @@
1
1
  require 'rack/oauth2/server/util'
2
- require 'rack/oauth2/server/error'
3
2
  require 'rack/oauth2/server/abstract'
4
3
  require 'rack/oauth2/server/authorize'
5
4
  require 'rack/oauth2/server/token'
@@ -1,3 +1,4 @@
1
1
  require 'rack/oauth2/server/abstract/handler'
2
2
  require 'rack/oauth2/server/abstract/request'
3
- require 'rack/oauth2/server/abstract/response'
3
+ require 'rack/oauth2/server/abstract/response'
4
+ require 'rack/oauth2/server/abstract/error'
@@ -0,0 +1,55 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ module Abstract
5
+ class Error < StandardError
6
+ attr_accessor :status, :error, :description, :uri
7
+
8
+ def initialize(status, error, description = nil, options = {})
9
+ @status = status
10
+ @error = error
11
+ @description = description
12
+ @uri = options[:uri]
13
+ end
14
+
15
+ def protocol_params
16
+ {
17
+ :error => error,
18
+ :error_description => description,
19
+ :error_uri => uri
20
+ }
21
+ end
22
+
23
+ def finish
24
+ response = Rack::Response.new
25
+ response.status = status
26
+ yield response if block_given?
27
+ unless response.redirect?
28
+ response.header['Content-Type'] = 'application/json'
29
+ response.write Util.compact_hash(protocol_params).to_json
30
+ end
31
+ response.finish
32
+ end
33
+ end
34
+
35
+ class BadRequest < Error
36
+ def initialize(error = :bad_request, description = nil, options = {})
37
+ super 400, error, description, options
38
+ end
39
+ end
40
+
41
+ class Unauthorized < Error
42
+ def initialize(error = :unauthorized, description = nil, options = {})
43
+ super 401, error, description, options
44
+ end
45
+ end
46
+
47
+ class Forbidden < Error
48
+ def initialize(error = :forbidden, description = nil, options = {})
49
+ super 403, error, description, options
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -3,10 +3,9 @@ module Rack
3
3
  module Server
4
4
  module Abstract
5
5
  class Handler
6
- attr_accessor :realm, :authenticator, :request, :response
6
+ attr_accessor :authenticator, :request, :response
7
7
 
8
- def initialize(realm = nil, &authenticator)
9
- @realm = realm
8
+ def initialize(&authenticator)
10
9
  @authenticator = authenticator
11
10
  end
12
11
 
@@ -15,14 +15,13 @@ module Rack
15
15
 
16
16
  def attr_missing_with_error_handling!
17
17
  if params['client_id'].present? && @client_id != params['client_id']
18
- invalid_client!("Multiple client credentials are provided.")
18
+ invalid_request! 'Multiple client credentials are provided.'
19
19
  end
20
20
  attr_missing_without_error_handling!
21
21
  rescue AttrRequired::AttrMissing => e
22
- invalid_request!(e.message, :state => @state, :redirect_uri => @redirect_uri)
22
+ invalid_request! e.message, :state => @state, :redirect_uri => @redirect_uri
23
23
  end
24
24
  alias_method_chain :attr_missing!, :error_handling
25
-
26
25
  end
27
26
  end
28
27
  end
@@ -8,11 +8,6 @@ module Rack
8
8
  def initialize(request)
9
9
  super([], 200, {})
10
10
  end
11
-
12
- def finish
13
- attr_missing!
14
- super
15
- end
16
11
  end
17
12
  end
18
13
  end
@@ -2,16 +2,14 @@ module Rack
2
2
  module OAuth2
3
3
  module Server
4
4
  class Authorize < Abstract::Handler
5
-
6
5
  def call(env)
7
6
  request = Request.new(env)
8
- request.profile.new(@realm, &@authenticator).call(env).finish
9
- rescue Error => e
7
+ request.profile.new(&@authenticator).call(env).finish
8
+ rescue Rack::OAuth2::Server::Abstract::Error => e
10
9
  e.finish
11
10
  end
12
11
 
13
12
  class Request < Abstract::Request
14
- include Error::Authorize
15
13
  attr_required :response_type
16
14
  attr_optional :redirect_uri, :state
17
15
 
@@ -27,36 +25,43 @@ module Rack
27
25
  Code
28
26
  when 'token'
29
27
  Token
30
- when 'code_and_token'
31
- CodeAndToken
32
28
  when ''
33
29
  attr_missing!
34
30
  else
35
- unsupported_response_type!("'#{params['response_type']}' isn't supported.")
31
+ unsupported_response_type! "#{CGI.escape params['response_type']} isn't supported."
36
32
  end
37
33
  end
38
-
39
34
  end
40
35
 
41
36
  class Response < Abstract::Response
42
37
  attr_required :redirect_uri
43
- attr_optional :state, :approved
38
+ attr_optional :state, :approval
44
39
 
45
40
  def initialize(request)
46
41
  @state = request.state
47
- @redirect_uri = Util.parse_uri(request.redirect_uri) if request.redirect_uri
48
42
  super
49
43
  end
50
44
 
51
45
  def approved?
52
- @approved
46
+ @approval
53
47
  end
54
48
 
55
49
  def approve!
56
- @approved = true
50
+ @approval = true
51
+ end
52
+
53
+ def protocol_params
54
+ {:state => state}
57
55
  end
58
- end
59
56
 
57
+ def finish
58
+ if approved?
59
+ attr_missing!
60
+ redirect Util.redirect_uri(redirect_uri, protocol_params_location, protocol_params)
61
+ end
62
+ super
63
+ end
64
+ end
60
65
  end
61
66
  end
62
67
  end
@@ -64,4 +69,4 @@ end
64
69
 
65
70
  require 'rack/oauth2/server/authorize/code'
66
71
  require 'rack/oauth2/server/authorize/token'
67
- require 'rack/oauth2/server/authorize/code_and_token'
72
+ require 'rack/oauth2/server/authorize/error'
@@ -5,8 +5,8 @@ module Rack
5
5
  class Code < Abstract::Handler
6
6
 
7
7
  def call(env)
8
- @request = Request.new(env)
9
- @response = Response.new(request)
8
+ @request = Request.new env
9
+ @response = Response.new request
10
10
  super
11
11
  end
12
12
 
@@ -21,25 +21,14 @@ module Rack
21
21
  class Response < Authorize::Response
22
22
  attr_required :code
23
23
 
24
- def finish
25
- if approved?
26
- params = {
27
- :code => code,
28
- :state => state
29
- }.delete_if do |key, value|
30
- value.blank?
31
- end
32
- redirect_uri.query = if redirect_uri.query
33
- [redirect_uri.query, params.to_query].join('&')
34
- else
35
- params.to_query
36
- end
37
- redirect redirect_uri.to_s
38
- end
39
- super
24
+ def protocol_params
25
+ super.merge(:code => code)
40
26
  end
41
- end
42
27
 
28
+ def protocol_params_location
29
+ :query
30
+ end
31
+ end
43
32
  end
44
33
  end
45
34
  end
@@ -0,0 +1,60 @@
1
+ module Rack
2
+ module OAuth2
3
+ module Server
4
+ class Authorize
5
+ class BadRequest < Abstract::BadRequest
6
+ attr_accessor :redirect_uri, :state, :protocol_params_location
7
+
8
+ def protocol_params
9
+ super.merge(:state => state)
10
+ end
11
+
12
+ def finish
13
+ if redirect_uri.present? && protocol_params_location.present?
14
+ super do |response|
15
+ response.redirect Util.redirect_uri(redirect_uri, protocol_params_location, protocol_params)
16
+ end
17
+ else
18
+ raise self
19
+ end
20
+ end
21
+ end
22
+
23
+ module ErrorMethods
24
+ DEFAULT_DESCRIPTION = {
25
+ :invalid_request => "The request is missing a required parameter, includes an unsupported parameter or parameter value, or is otherwise malformed.",
26
+ :unauthorized_client => "The client is not authorized to use the requested response type.",
27
+ :access_denied => "The end-user or authorization server denied the request.",
28
+ :unsupported_response_type => "The requested response type is not supported by the authorization server.",
29
+ :invalid_scope => "The requested scope is invalid, unknown, or malformed."
30
+ }
31
+
32
+ def self.included(klass)
33
+ DEFAULT_DESCRIPTION.each do |error, default_description|
34
+ klass.class_eval <<-ERROR
35
+ def #{error}!(description = "#{default_description}", options = {})
36
+ bad_request! :#{error}, description, options.merge(:redirect => true)
37
+ end
38
+ ERROR
39
+ end
40
+ end
41
+
42
+ def bad_request!(error = :bad_request, description = nil, options = {})
43
+ exception = BadRequest.new error, description, options
44
+ exception.protocol_params_location = case response_type
45
+ when :code
46
+ :query
47
+ when :token
48
+ :fragment
49
+ end
50
+ exception.state = state
51
+ exception.redirect_uri = redirect_uri if options[:redirect]
52
+ raise exception
53
+ end
54
+ end
55
+
56
+ Request.send :include, ErrorMethods
57
+ end
58
+ end
59
+ end
60
+ end
@@ -3,10 +3,9 @@ module Rack
3
3
  module Server
4
4
  class Authorize
5
5
  class Token < Abstract::Handler
6
-
7
6
  def call(env)
8
- @request = Request.new(env)
9
- @response = Response.new(request)
7
+ @request = Request.new env
8
+ @response = Response.new request
10
9
  super
11
10
  end
12
11
 
@@ -19,30 +18,22 @@ module Rack
19
18
  end
20
19
 
21
20
  class Response < Authorize::Response
22
- attr_required :access_token
23
- attr_optional :expires_in, :scope
21
+ attr_required :access_token, :token_type
22
+ attr_optional :refresh_token, :expires_in, :scope
24
23
 
25
- def finish
26
- if approved?
27
- params = {
28
- :access_token => access_token,
29
- :expires_in => expires_in,
30
- :scope => Array(scope).join(' '),
31
- :state => state
32
- }.delete_if do |key, value|
33
- value.blank?
34
- end
35
- redirect_uri.fragment = if redirect_uri.fragment
36
- [redirect_uri.fragment, params.to_query].join('&')
37
- else
38
- params.to_query
39
- end
40
- redirect redirect_uri.to_s
41
- end
42
- super
24
+ def protocol_params
25
+ super.merge(
26
+ :access_token => access_token,
27
+ :expires_in => expires_in,
28
+ :refresh_token => refresh_token,
29
+ :scope => Array(scope).join(' ')
30
+ )
43
31
  end
44
- end
45
32
 
33
+ def protocol_params_location
34
+ :fragment
35
+ end
36
+ end
46
37
  end
47
38
  end
48
39
  end
@@ -1,79 +1 @@
1
- require 'rack/auth/abstract/request'
2
-
3
- module Rack
4
- module OAuth2
5
- module Server
6
- class Resource < Abstract::Handler
7
-
8
- def initialize(app, realm = nil, &authenticator)
9
- @app = app
10
- super(realm, &authenticator)
11
- end
12
-
13
- def call(env)
14
- request = Request.new(env, realm)
15
- if request.oauth2?
16
- authenticate!(request)
17
- env[ACCESS_TOKEN] = request.access_token
18
- end
19
- @app.call(env)
20
- rescue Error => e
21
- e.realm = realm
22
- e.finish
23
- end
24
-
25
- private
26
-
27
- def authenticate!(request)
28
- @authenticator.call(request)
29
- end
30
-
31
- class Request < Rack::Request
32
- include Error::Resource
33
-
34
- attr_accessor :realm
35
-
36
- def initialize(env, realm = nil)
37
- @env = env
38
- @realm = realm
39
- @auth_header = Rack::Auth::AbstractRequest.new(env)
40
- end
41
-
42
- def oauth2?
43
- access_token.present?
44
- end
45
-
46
- def access_token
47
- tokens = [access_token_in_haeder, access_token_in_payload].compact
48
- case Array(tokens).size
49
- when 0
50
- nil
51
- when 1
52
- tokens.first
53
- else
54
- invalid_request!('Both Authorization header and payload includes oauth_token.', :realm => realm)
55
- end
56
- end
57
-
58
- def access_token_in_haeder
59
- if @auth_header.provided? && @auth_header.scheme == :oauth && @auth_header.params !~ /oauth_signature_method/
60
- @auth_header.params
61
- else
62
- nil
63
- end
64
- end
65
-
66
- def access_token_in_payload
67
- if params['oauth_token'] && !params['oauth_signature_method']
68
- params['oauth_token']
69
- else
70
- nil # This is OAuth1 request
71
- end
72
- end
73
-
74
- end
75
-
76
- end
77
- end
78
- end
79
- end
1
+ require 'rack/oauth2/server/resource/bearer'