rack-oauth2 0.0.0 → 0.0.1

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.
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ begin
11
11
  gem.homepage = 'http://github.com/nov/rack-oauth2'
12
12
  gem.authors = ['nov matake']
13
13
  gem.add_dependency 'json'
14
+ gem.add_dependency 'activesupport'
14
15
  gem.add_development_dependency 'rspec', '>= 1.2.9'
15
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
17
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.1
@@ -48,7 +48,7 @@ post '/oauth/authorize' do
48
48
  response.expires_in = 3600
49
49
  end
50
50
  else
51
- raise Rack::OAuth2::Server::Unauthorized.new(:access_denied, 'User rejected the requested access.')
51
+ raise Rack::OAuth2::Server::Unauthorized.new(:access_denied, 'User rejected the requested access.', :redirect_uri => request.redirect_uri, :state => request.state)
52
52
  end
53
53
  end
54
54
  authorization_endpoint.call(env)
@@ -3,13 +3,17 @@ module Rack
3
3
  module Server
4
4
  module Abstract
5
5
  class Request < Rack::Request
6
+ attr_accessor :client_id
7
+
6
8
  def initialize(env)
7
9
  super
8
10
  verify_required_params!
11
+ @client_id = params['client_id']
12
+ @scope = Array(params['scope'].to_s.split(' '))
9
13
  end
10
14
 
11
15
  def required_params
12
- raise "Implement verify_required_params! in #{self.class}"
16
+ raise "Implement #{self.class}#verify_required_params!"
13
17
  end
14
18
 
15
19
  def verify_required_params!
@@ -17,8 +21,8 @@ module Rack
17
21
  required_params.each do |key|
18
22
  missing_params << key unless params[key.to_s]
19
23
  end
20
- unless missing_params.empty?
21
- raise BadRequest.new(:invalid_request, "'#{missing_params.join('\', \'')}' required")
24
+ unless missing_params.blank?
25
+ raise BadRequest.new(:invalid_request, "'#{missing_params.join('\', \'')}' required", :state => @state, :redirect_uri => @redirect_uri)
22
26
  end
23
27
  end
24
28
  end
@@ -22,10 +22,17 @@ module Rack
22
22
 
23
23
  def finish
24
24
  if approved?
25
- query_params = Array(redirect_uri.query)
26
- query_params << "code=#{URI.encode code}"
27
- query_params << "state=#{URI.encode state}" if state
28
- redirect_uri.query = query_params.join('&')
25
+ params = {
26
+ :code => code,
27
+ :state => state
28
+ }.delete_if do |key, value|
29
+ value.blank?
30
+ end
31
+ redirect_uri.query = if redirect_uri.query
32
+ [redirect_uri.query, params.to_query].join('&')
33
+ else
34
+ params.to_query
35
+ end
29
36
  redirect redirect_uri.to_s
30
37
  end
31
38
  super
@@ -22,12 +22,19 @@ module Rack
22
22
 
23
23
  def finish
24
24
  if approved?
25
- fragment = Array(redirect_uri.fragment)
26
- fragment << "access_token=#{URI.encode access_token}"
27
- fragment << "expires_in=#{URI.encode expires_in.to_s}" if expires_in
28
- fragment << "scope=#{URI.encode Array(scope).join(' ')}" if scope
29
- query_params << "state=#{URI.encode state}" if state
30
- redirect_uri.fragment = fragment.join('&')
25
+ params = {
26
+ :access_token => access_token,
27
+ :expires_in => expires_in,
28
+ :scope => Array(scope).join(' '),
29
+ :state => state
30
+ }.delete_if do |key, value|
31
+ value.blank?
32
+ end
33
+ redirect_uri.fragment = if redirect_uri.fragment
34
+ [redirect_uri.fragment, params.to_query].join('&')
35
+ else
36
+ params.to_query
37
+ end
31
38
  redirect redirect_uri.to_s
32
39
  end
33
40
  super
@@ -15,10 +15,11 @@ module Rack
15
15
 
16
16
  def initialize(env)
17
17
  super
18
- @client_id = params['client_id']
19
- @redirect_uri = URI.parse(params['redirect_uri']) rescue nil
20
- @scope = Array(params['scope'].to_s.split(' '))
18
+ @redirect_uri = URI.parse(params['redirect_uri'])
21
19
  @state = params['state']
20
+ rescue URI::InvalidURIError
21
+ # NOTE: can't redirect in this case.
22
+ raise BadRequest.new(:invalid_request, 'Invalid redirect_uri format.')
22
23
  end
23
24
 
24
25
  def required_params
@@ -34,7 +35,7 @@ module Rack
34
35
  when 'token_and_code'
35
36
  CodeAndToken
36
37
  else
37
- raise BadRequest.new(:unsupported_response_type, "'#{params['response_type']}' isn't supported.")
38
+ raise BadRequest.new(:unsupported_response_type, "'#{params['response_type']}' isn't supported.", :state => state, :redirect_uri => redirect_uri)
38
39
  end
39
40
  end
40
41
  end
@@ -3,37 +3,57 @@ module Rack
3
3
  module Server
4
4
 
5
5
  class Error < StandardError
6
- attr_accessor :code, :error, :description, :uri, :state
6
+ attr_accessor :code, :error, :description, :uri, :redirect_uri, :state
7
7
 
8
- def initialize(code, error, description, options = {})
9
- @code = code
10
- @error = error
11
- @description = description
12
- @uri = options[:uri]
13
- @state = options[:state]
8
+ def initialize(code, error, description = "", options = {})
9
+ @code = code
10
+ @error = error
11
+ @description = description
12
+ @uri = options[:uri]
13
+ @state = options[:state]
14
+ @redirect_uri = options[:redirect_uri]
14
15
  end
15
16
 
16
17
  def finish
17
- [code, {'Content-Type' => 'application/json'}, response.to_json]
18
- end
19
-
20
- def response
21
- response = {:error => error}
22
- response[:error_description] = description if description
23
- response[:error_uri] = uri if uri
24
- response[:state] = state if state
25
- response
18
+ params = {
19
+ :error => error,
20
+ :error_description => description,
21
+ :error_uri => uri,
22
+ :state => state
23
+ }.delete_if do |key, value|
24
+ value.blank?
25
+ end
26
+ if redirect_uri
27
+ _redirect_uri_ = case redirect_uri
28
+ when URI::Generic
29
+ redirect_uri
30
+ when String
31
+ URI.parse(redirect_uri)
32
+ else
33
+ raise "Invalid redirect_uri is given. String or URI::Generic is require."
34
+ end
35
+ _redirect_uri_.query = if _redirect_uri_.query
36
+ [_redirect_uri_.query, params.to_query].join('&')
37
+ else
38
+ params.to_query
39
+ end
40
+ response = Rack::Response.new
41
+ response.redirect _redirect_uri_.to_s
42
+ response.finish
43
+ else
44
+ [code, {'Content-Type' => 'application/json'}, params.to_json]
45
+ end
26
46
  end
27
47
  end
28
48
 
29
49
  class Unauthorized < Error
30
- def initialize(error, description, options = {})
50
+ def initialize(error, description = "", options = {})
31
51
  super(401, error, description, options)
32
52
  end
33
53
  end
34
54
 
35
55
  class BadRequest < Error
36
- def initialize(error, description, options = {})
56
+ def initialize(error, description = "", options = {})
37
57
  super(400, error, description, options)
38
58
  end
39
59
  end
@@ -11,14 +11,16 @@ module Rack
11
11
  end
12
12
 
13
13
  class Request < Token::Request
14
- attr_accessor :client_id, :client_secret, :code, :redirect_uri, :scope
14
+ attr_accessor :code, :redirect_uri, :scope
15
15
 
16
16
  def initialize(env)
17
17
  super
18
18
  @grant_type = 'authorization_code'
19
19
  @code = params['code']
20
- @redirect_uri = URI.parse(params['redirect_uri']) rescue nil
20
+ @redirect_uri = URI.parse(params['redirect_uri'])
21
21
  @scope = Array(params['scope'].to_s.split(' '))
22
+ rescue URI::InvalidURIError
23
+ raise BadRequest.new(:invalid_request, 'Invalid redirect_uri format.')
22
24
  end
23
25
 
24
26
  def required_params
@@ -12,13 +12,12 @@ module Rack
12
12
  end
13
13
 
14
14
  class Request < Abstract::Request
15
- attr_accessor :client_id, :client_secret, :code, :redirect_uri, :scope
15
+ attr_accessor :grant_type, :client_secret
16
16
 
17
17
  def initialize(env)
18
18
  super
19
- @client_id = params['client_id']
19
+ @grant_type = params['grant_type']
20
20
  @client_secret = params['client_secret']
21
- @scope = Array(params['scope'].to_s.split(' '))
22
21
  end
23
22
 
24
23
  def required_params
data/lib/rack/oauth2.rb CHANGED
@@ -1,2 +1,4 @@
1
+ require 'rack'
1
2
  require 'json'
3
+ require 'active_support/core_ext'
2
4
  require 'rack/oauth2/server'
@@ -0,0 +1,82 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rack-oauth2}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["nov matake"]
12
+ s.date = %q{2010-09-15}
13
+ s.description = %q{Rack Middleware for OAuth2 Client & Server, currently working on server code first.}
14
+ s.email = %q{nov@matake.jp}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "example/server/authorize.rb",
27
+ "example/server/token.rb",
28
+ "lib/rack/oauth2.rb",
29
+ "lib/rack/oauth2/server.rb",
30
+ "lib/rack/oauth2/server/abstract.rb",
31
+ "lib/rack/oauth2/server/abstract/handler.rb",
32
+ "lib/rack/oauth2/server/abstract/request.rb",
33
+ "lib/rack/oauth2/server/abstract/response.rb",
34
+ "lib/rack/oauth2/server/authorization.rb",
35
+ "lib/rack/oauth2/server/authorization/code.rb",
36
+ "lib/rack/oauth2/server/authorization/code_and_token.rb",
37
+ "lib/rack/oauth2/server/authorization/token.rb",
38
+ "lib/rack/oauth2/server/error.rb",
39
+ "lib/rack/oauth2/server/token.rb",
40
+ "lib/rack/oauth2/server/token/assertion.rb",
41
+ "lib/rack/oauth2/server/token/authorization_code.rb",
42
+ "lib/rack/oauth2/server/token/password.rb",
43
+ "lib/rack/oauth2/server/token/refresh_token.rb",
44
+ "rack-oauth2.gemspec",
45
+ "spec/rack/oauth2/server/authorization/code_spec.rb",
46
+ "spec/rack/oauth2/server/authorization_spec.rb",
47
+ "spec/rack/oauth2/server/error_spec.rb",
48
+ "spec/spec.opts",
49
+ "spec/spec_helper.rb"
50
+ ]
51
+ s.homepage = %q{http://github.com/nov/rack-oauth2}
52
+ s.rdoc_options = ["--charset=UTF-8"]
53
+ s.require_paths = ["lib"]
54
+ s.rubygems_version = %q{1.3.7}
55
+ s.summary = %q{Rack Middleware for OAuth2 Client & Server}
56
+ s.test_files = [
57
+ "spec/rack/oauth2/server/authorization/code_spec.rb",
58
+ "spec/rack/oauth2/server/authorization_spec.rb",
59
+ "spec/rack/oauth2/server/error_spec.rb",
60
+ "spec/spec_helper.rb"
61
+ ]
62
+
63
+ if s.respond_to? :specification_version then
64
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
65
+ s.specification_version = 3
66
+
67
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
68
+ s.add_runtime_dependency(%q<json>, [">= 0"])
69
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
70
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
71
+ else
72
+ s.add_dependency(%q<json>, [">= 0"])
73
+ s.add_dependency(%q<activesupport>, [">= 0"])
74
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
75
+ end
76
+ else
77
+ s.add_dependency(%q<json>, [">= 0"])
78
+ s.add_dependency(%q<activesupport>, [">= 0"])
79
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
80
+ end
81
+ end
82
+
@@ -0,0 +1,42 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Server::Authorization::Code do
4
+
5
+ context "when authorized" do
6
+
7
+ before do
8
+ # NOTE: for some reason, test fails when called Rack::OAuth2::Server::Authorization::Code directly
9
+ @app = Rack::OAuth2::Server::Authorization.new(simple_app) do |request, response|
10
+ response.approve!
11
+ response.code = "authorization_code"
12
+ end
13
+ @request = Rack::MockRequest.new @app
14
+ end
15
+
16
+ it "should redirect to redirect_uri with authorization code" do
17
+ response = @request.get("/?response_type=code&client_id=client&redirect_uri=http://client.example.com/callback")
18
+ response.status.should == 302
19
+ response.location.should == "http://client.example.com/callback?code=authorization_code"
20
+ end
21
+
22
+ end
23
+
24
+ context "when denied" do
25
+
26
+ before do
27
+ # NOTE: for some reason, test fails when called Rack::OAuth2::Server::Authorization::Code directly
28
+ @app = Rack::OAuth2::Server::Authorization.new(simple_app) do |request, response|
29
+ raise Rack::OAuth2::Server::Unauthorized.new(:access_denied, 'User rejected the requested access.', :redirect_uri => request.redirect_uri)
30
+ end
31
+ @request = Rack::MockRequest.new @app
32
+ end
33
+
34
+ it "should redirect to redirect_uri with authorization code" do
35
+ response = @request.get("/?response_type=code&client_id=client&redirect_uri=http://client.example.com/callback")
36
+ response.status.should == 302
37
+ response.location.should == "http://client.example.com/callback?error_description=User+rejected+the+requested+access.&error=access_denied"
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Server::Authorization do
4
+
5
+ before do
6
+ @app = Rack::OAuth2::Server::Authorization.new(simple_app)
7
+ @request = Rack::MockRequest.new @app
8
+ end
9
+
10
+ it "should support realm" do
11
+ app = Rack::OAuth2::Server::Authorization.new(simple_app, "server.example.com")
12
+ app.realm.should == "server.example.com"
13
+ end
14
+
15
+ context "when any required parameters are missing" do
16
+ it "should return invalid_request error" do
17
+ assert_error_response(:json, :invalid_request) do
18
+ @request.get('/')
19
+ end
20
+ assert_error_response(:json, :invalid_request) do
21
+ @request.get('/?response_type=code')
22
+ end
23
+ assert_error_response(:json, :invalid_request) do
24
+ @request.get('/?response_type=code&client_id=client')
25
+ end
26
+ assert_error_response(:json, :invalid_request) do
27
+ @request.get('/?response_type=code&redirect_uri=http://client.example.com/callback')
28
+ end
29
+ assert_error_response(:json, :invalid_request) do
30
+ @request.get('/?client_id=client&redirect_uri=http://client.example.com/callback')
31
+ end
32
+ assert_error_response(:json, :invalid_request) do
33
+ @request.get('/?response_type=code&redirect_uri=http://client.example.com/callback')
34
+ end
35
+ end
36
+ end
37
+
38
+ context "when unsupported response_type is given" do
39
+ it "should return unsupported_response_type error" do
40
+ assert_error_response(:query, :unsupported_response_type) do
41
+ @request.get('/?response_type=hello&client_id=client&redirect_uri=http://client.example.com/callback')
42
+ end
43
+ end
44
+ end
45
+
46
+ context "when all required parameters are valid" do
47
+ it "should succeed" do
48
+ response = @request.get('/?response_type=code&client_id=client&redirect_uri=http://client.example.com/callback')
49
+ response.status.should == 200
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Server::Error, '#finish' do
4
+
5
+ context "when state is given" do
6
+ it "should return state as error response" do
7
+ error = Rack::OAuth2::Server::Error.new(400, :invalid_request, "Something Invalid!!", :state => "anything")
8
+ status, header, body = error.finish
9
+ body.should match("\"state\":\"anything\"")
10
+ end
11
+ end
12
+
13
+ context "when redirect_uri is given" do
14
+ before do
15
+ @params = {
16
+ :error => :invalid_request,
17
+ :error_description => "Something invalid!!",
18
+ :redirect_uri => "http://client.example.com"
19
+ }
20
+ @error = Rack::OAuth2::Server::Error.new(400, @params[:error], @params[:error_description], :redirect_uri => @params[:redirect_uri])
21
+ end
22
+
23
+ it "should redirect to redirect_uri with error message in query string" do
24
+ status, header, body = @error.finish
25
+ status.should == 302
26
+ header['Content-Type'].should == "text/html"
27
+ header['Location'].should == "#{@params.delete(:redirect_uri)}?#{@params.to_query}"
28
+ end
29
+ end
30
+
31
+ context "when redirect_uri isn't given" do
32
+ before do
33
+ @params = {
34
+ :error => :invalid_request,
35
+ :error_description => "Something invalid!!"
36
+ }
37
+ @error = Rack::OAuth2::Server::Error.new(400, @params[:error], @params[:error_description])
38
+ end
39
+
40
+ it "should return failure response with error message in json body" do
41
+ status, header, body = @error.finish
42
+ body.should == @params.to_json
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ describe Rack::OAuth2::Server::BadRequest do
49
+ it "should use 400 as status" do
50
+ error = Rack::OAuth2::Server::BadRequest.new(:invalid_request)
51
+ error.code.should == 400
52
+ end
53
+ end
54
+
55
+ describe Rack::OAuth2::Server::Unauthorized do
56
+ it "should use 401 as status" do
57
+ error = Rack::OAuth2::Server::Unauthorized.new(:unauthorized_client)
58
+ error.code.should == 401
59
+ end
60
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,7 +3,26 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'rack/oauth2'
4
4
  require 'spec'
5
5
  require 'spec/autorun'
6
+ require 'rack/mock'
6
7
 
7
8
  Spec::Runner.configure do |config|
8
9
 
9
10
  end
11
+
12
+ def simple_app
13
+ lambda do |env|
14
+ [ 200, {'Content-Type' => 'text/plain'}, ["HELLO"] ]
15
+ end
16
+ end
17
+
18
+ def assert_error_response(format, error)
19
+ response = yield
20
+ case format
21
+ when :json
22
+ response.status.should == 400
23
+ response.body.should match("\"error\":\"#{error}\"")
24
+ when :query
25
+ response.status.should == 302
26
+ response.location.should match("error=#{error}")
27
+ end
28
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 0
10
- version: 0.0.0
9
+ - 1
10
+ version: 0.0.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - nov matake
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-13 00:00:00 +09:00
18
+ date: 2010-09-15 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -33,9 +33,23 @@ dependencies:
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
- name: rspec
36
+ name: activesupport
37
37
  prerelease: false
38
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
39
53
  none: false
40
54
  requirements:
41
55
  - - ">="
@@ -47,7 +61,7 @@ dependencies:
47
61
  - 9
48
62
  version: 1.2.9
49
63
  type: :development
50
- version_requirements: *id002
64
+ version_requirements: *id003
51
65
  description: Rack Middleware for OAuth2 Client & Server, currently working on server code first.
52
66
  email: nov@matake.jp
53
67
  executables: []
@@ -82,7 +96,10 @@ files:
82
96
  - lib/rack/oauth2/server/token/authorization_code.rb
83
97
  - lib/rack/oauth2/server/token/password.rb
84
98
  - lib/rack/oauth2/server/token/refresh_token.rb
85
- - spec/rack/oauth2_spec.rb
99
+ - rack-oauth2.gemspec
100
+ - spec/rack/oauth2/server/authorization/code_spec.rb
101
+ - spec/rack/oauth2/server/authorization_spec.rb
102
+ - spec/rack/oauth2/server/error_spec.rb
86
103
  - spec/spec.opts
87
104
  - spec/spec_helper.rb
88
105
  has_rdoc: true
@@ -120,5 +137,7 @@ signing_key:
120
137
  specification_version: 3
121
138
  summary: Rack Middleware for OAuth2 Client & Server
122
139
  test_files:
123
- - spec/rack/oauth2_spec.rb
140
+ - spec/rack/oauth2/server/authorization/code_spec.rb
141
+ - spec/rack/oauth2/server/authorization_spec.rb
142
+ - spec/rack/oauth2/server/error_spec.rb
124
143
  - spec/spec_helper.rb
@@ -1,7 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '../spec_helper')
2
-
3
- describe Rack::OAuth2 do
4
- it "fails" do
5
- fail "hey buddy, you should probably rename this file and start specing for real"
6
- end
7
- end