rack-oauth2 0.2.3 → 0.3.0.alpha

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