rack-oauth2 0.0.0 → 0.0.1

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