hancock-client 0.0.7 → 0.0.8
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/README.md +10 -15
- data/Rakefile +3 -1
- data/lib/hancock-client.rb +10 -17
- data/lib/hancock-client/default.rb +20 -0
- data/lib/hancock-client/helpers/rack.rb +55 -0
- data/lib/hancock-client/middleware.rb +7 -0
- data/lib/hancock-client/mock_middleware.rb +20 -0
- data/lib/{sinatra/hancock → hancock-client}/sso.rb +8 -31
- data/spec/hancock_sinatra_spec.rb +12 -14
- data/spec/mock_sso_user_spec.rb +26 -0
- data/spec/pattern_exclusion_spec.rb +30 -0
- data/spec/spec_helper.rb +5 -16
- metadata +21 -7
- data/lib/rack-openid.rb +0 -195
- data/lib/sinatra/hancock/mock.rb +0 -0
data/README.md
CHANGED
@@ -3,18 +3,11 @@ hancock-client
|
|
3
3
|
|
4
4
|
A gem that integrates [sinatra][sinatra] applications into the Hancock SSO
|
5
5
|
environment. It also doubles as rack middleware that can be used in
|
6
|
-
rails(>= 2.3.2) and
|
6
|
+
rails(>= 2.3.2) and sinatra applications.
|
7
7
|
|
8
8
|
Dependencies
|
9
9
|
============
|
10
|
-
%
|
11
|
-
*** CURRENT SOURCES ***
|
12
|
-
|
13
|
-
http://gems.rubyforge.org
|
14
|
-
% sudo gem sources -a http://gems.github.com
|
15
|
-
http://gems.github.com added to sources
|
16
|
-
|
17
|
-
% sudo gem install sinatra hancock haml
|
10
|
+
% sudo geminstaller
|
18
11
|
|
19
12
|
testing
|
20
13
|
=======
|
@@ -30,22 +23,24 @@ The goal is to make it simple to write sso enabled apps.
|
|
30
23
|
require 'hancock-client'
|
31
24
|
require 'logger'
|
32
25
|
|
33
|
-
# OpenID writes to STDERR by default. This is closed under passenger so
|
34
|
-
# to make this reliable you should have openid write failures somewhere.
|
35
|
-
OpenID::Util.logger = Logger.new(Dir.tmpdir + "/openid.log")
|
36
|
-
|
37
26
|
class HancockClientDemo < Sinatra::Default
|
38
27
|
set :views, File.dirname(__FILE__) + '/views'
|
39
28
|
set :public, File.dirname(__FILE__) + '/public'
|
40
|
-
use Hancock::Client::
|
29
|
+
use Hancock::Client::Middleware do |sso|
|
41
30
|
sso.sso_url = 'http://hancock.atmos.org/sso'
|
31
|
+
sso.exclude_paths = %w(/api/)
|
42
32
|
end
|
43
33
|
|
44
34
|
get '/' do
|
45
|
-
haml(%Q{%h3= "#{
|
35
|
+
haml(%Q{%h3= "#{sso_user_full_name} - #{sso_user_email}"})
|
46
36
|
end
|
47
37
|
end
|
48
38
|
|
49
39
|
run HancockClientDemo
|
50
40
|
|
41
|
+
Feedback
|
42
|
+
========
|
43
|
+
* [Google Group][googlegroup]
|
44
|
+
|
51
45
|
[sinatra]: http://www.sinatrarb.com
|
46
|
+
[googlegroup]: http://groups.google.com/group/hancock-users
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'spec/rake/spectask'
|
|
6
6
|
require 'cucumber/rake/task'
|
7
7
|
|
8
8
|
GEM = "hancock-client"
|
9
|
-
GEM_VERSION = "0.0.
|
9
|
+
GEM_VERSION = "0.0.8"
|
10
10
|
AUTHOR = "Corey Donohoe"
|
11
11
|
EMAIL = ['atmos@atmos.org', 'tim@spork.in']
|
12
12
|
HOMEPAGE = "http://github.com/atmos/hancock-client"
|
@@ -28,6 +28,8 @@ spec = Gem::Specification.new do |s|
|
|
28
28
|
s.add_dependency "sinatra", "~>0.9.2"
|
29
29
|
s.add_dependency "ruby-openid", "~>2.1.6"
|
30
30
|
s.add_dependency "haml", "~>2.0.9"
|
31
|
+
s.add_dependency "rack-openid", "~>0.2"
|
32
|
+
|
31
33
|
s.require_path = 'lib'
|
32
34
|
s.autorequire = GEM
|
33
35
|
s.files = %w(LICENSE README.md Rakefile) + Dir.glob("{lib,spec}/**/*")
|
data/lib/hancock-client.rb
CHANGED
@@ -3,25 +3,18 @@ require 'sinatra/base'
|
|
3
3
|
|
4
4
|
gem 'ruby-openid', '>=2.1.6'
|
5
5
|
require 'openid'
|
6
|
+
require 'openid/store/memory'
|
7
|
+
|
8
|
+
gem 'rack-openid', '>=0.2'
|
9
|
+
require 'rack-openid'
|
6
10
|
|
7
11
|
gem 'haml', '~>2.0.9'
|
8
12
|
require 'haml'
|
9
13
|
|
10
|
-
require
|
11
|
-
|
12
|
-
module Hancock
|
13
|
-
module Client
|
14
|
-
class Default < ::Sinatra::Base
|
15
|
-
enable :sessions
|
16
|
-
disable :raise_errors
|
17
|
-
disable :show_exceptions
|
18
|
-
|
19
|
-
set :sso_url, nil
|
14
|
+
require 'tmpdir'
|
20
15
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
16
|
+
require File.dirname(__FILE__)+'/hancock-client/helpers/rack'
|
17
|
+
require File.dirname(__FILE__)+'/hancock-client/default'
|
18
|
+
require File.dirname(__FILE__)+'/hancock-client/sso'
|
19
|
+
require File.dirname(__FILE__)+'/hancock-client/middleware'
|
20
|
+
require File.dirname(__FILE__)+'/hancock-client/mock_middleware'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Hancock
|
2
|
+
module Client
|
3
|
+
class DefaultMiddleware < ::Sinatra::Base
|
4
|
+
enable :sessions
|
5
|
+
enable :raise_errors
|
6
|
+
disable :show_exceptions
|
7
|
+
|
8
|
+
set :sso_url, nil
|
9
|
+
set :exclude_paths, nil
|
10
|
+
|
11
|
+
def sso_url=(url)
|
12
|
+
options.sso_url = url
|
13
|
+
end
|
14
|
+
|
15
|
+
def exclude_paths=(paths)
|
16
|
+
options.exclude_paths = paths
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Hancock
|
2
|
+
module Client
|
3
|
+
module Helpers
|
4
|
+
module Rack
|
5
|
+
def sso_logged_in?
|
6
|
+
session[:sso] && sso_user_id
|
7
|
+
end
|
8
|
+
|
9
|
+
def sso_login_as(user_id, sreg_params)
|
10
|
+
session.delete(:last_oidreq)
|
11
|
+
session.delete('OpenID::Consumer::last_requested_endpoint')
|
12
|
+
session.delete('OpenID::Consumer::DiscoveredServices::OpenID::Consumer::')
|
13
|
+
|
14
|
+
session[:sso] ||= { }
|
15
|
+
session[:sso][:user_id] = user_id
|
16
|
+
sreg_params.each { |key, value| session[:sso][key.to_sym] = value.to_s }
|
17
|
+
end
|
18
|
+
|
19
|
+
def sso_user_id
|
20
|
+
session[:sso][:user_id]
|
21
|
+
end
|
22
|
+
|
23
|
+
def sso_user_email
|
24
|
+
session[:sso][:email]
|
25
|
+
end
|
26
|
+
|
27
|
+
def sso_user_first_name
|
28
|
+
session[:sso][:first_name]
|
29
|
+
end
|
30
|
+
|
31
|
+
def sso_user_last_name
|
32
|
+
session[:sso][:last_name]
|
33
|
+
end
|
34
|
+
|
35
|
+
def sso_user_full_name
|
36
|
+
"#{session[:sso][:first_name]} #{session[:sso][:last_name]}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def absolute_url(suffix = nil)
|
40
|
+
port_part = case request.scheme
|
41
|
+
when "http"
|
42
|
+
request.port == 80 ? "" : ":#{request.port}"
|
43
|
+
when "https"
|
44
|
+
request.port == 443 ? "" : ":#{request.port}"
|
45
|
+
end
|
46
|
+
"#{request.scheme}://#{request.host}#{port_part}#{suffix}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def excluded_path?
|
50
|
+
options.exclude_paths && options.exclude_paths.include?(request.path_info)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Hancock
|
2
|
+
module Client
|
3
|
+
class MockMiddleware < DefaultMiddleware
|
4
|
+
helpers Hancock::Client::Helpers::Rack
|
5
|
+
|
6
|
+
before do
|
7
|
+
unless sso_logged_in?
|
8
|
+
sso_login_as((0..42).pick, {
|
9
|
+
:email => "#{/\w{3,8}/.gen.downcase}@example.com",
|
10
|
+
:first_name => Randgen.first_name,
|
11
|
+
:last_name => Randgen.first_name
|
12
|
+
})
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
register Hancock::Client::SSO
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,33 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
module Sinatra
|
5
|
-
module Hancock
|
1
|
+
module Hancock
|
2
|
+
module Client
|
6
3
|
module SSO
|
7
|
-
module Helpers
|
8
|
-
def absolute_url(suffix = nil)
|
9
|
-
port_part = case request.scheme
|
10
|
-
when "http"
|
11
|
-
request.port == 80 ? "" : ":#{request.port}"
|
12
|
-
when "https"
|
13
|
-
request.port == 443 ? "" : ":#{request.port}"
|
14
|
-
end
|
15
|
-
"#{request.scheme}://#{request.host}#{port_part}#{suffix}"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
4
|
def self.registered(app)
|
20
|
-
app.use(Rack::OpenID)
|
21
|
-
app.helpers Hancock::
|
22
|
-
|
23
|
-
app.not_found do
|
24
|
-
next if session[:user_id]
|
25
|
-
end
|
5
|
+
app.use(Rack::OpenID, OpenID::Store::Filesystem.new("#{Dir.tmpdir}/openid"))
|
6
|
+
app.helpers Hancock::Client::Helpers::Rack
|
26
7
|
|
27
8
|
app.before do
|
28
9
|
next if request.path_info == '/sso/login'
|
29
10
|
next if request.path_info == '/sso/logout'
|
30
|
-
next if
|
11
|
+
next if excluded_path?
|
12
|
+
next if sso_logged_in?
|
31
13
|
throw(:halt, [302, {'Location' => '/sso/login'}, ''])
|
32
14
|
end
|
33
15
|
|
@@ -41,13 +23,8 @@ module Sinatra
|
|
41
23
|
elsif openid = request.env["rack.openid.response"]
|
42
24
|
if openid.status == :success
|
43
25
|
if contact_id = openid.display_identifier.split("/").last
|
44
|
-
|
45
|
-
|
46
|
-
session.delete('OpenID::Consumer::DiscoveredServices::OpenID::Consumer::')
|
47
|
-
|
48
|
-
session[:user_id] = contact_id
|
49
|
-
params = openid.message.get_args("http://openid.net/extensions/sreg/1.1")
|
50
|
-
params.each { |key, value| session[key.to_sym] = value.to_s }
|
26
|
+
sreg_params = openid.message.get_args("http://openid.net/extensions/sreg/1.1")
|
27
|
+
sso_login_as(contact_id, sreg_params)
|
51
28
|
redirect '/'
|
52
29
|
else
|
53
30
|
raise "No contact could be found for #{openid.display_identifier}"
|
@@ -1,25 +1,23 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
describe 'Hancock::Client::Default' do
|
4
|
+
def app
|
5
|
+
@app = Rack::Builder.new do
|
6
|
+
use Hancock::Client::Middleware do |sso|
|
7
|
+
sso.sso_url = 'http://localhost:20000'
|
8
|
+
end
|
9
|
+
map '/' do
|
10
|
+
run Proc.new {|env| [200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ['HELLO']] }
|
11
|
+
end
|
12
|
+
end
|
10
13
|
end
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
it "should protect the root url from all HTTP verbs" do
|
16
|
+
%w(get post put head delete).each do |verb|
|
14
17
|
send(verb, '/')
|
15
18
|
last_response.headers['Location'].should eql('/sso/login')
|
16
19
|
get last_response.headers['Location']
|
17
20
|
last_response.headers['Location'].should eql('http://localhost:20000/login?return_to=http://example.org/sso/login')
|
18
21
|
end
|
19
22
|
end
|
20
|
-
it "should greet the user when authenticated" do
|
21
|
-
pending
|
22
|
-
get '/'
|
23
|
-
last_response.should have_selector('p')
|
24
|
-
end
|
25
23
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
class MyMockApp
|
4
|
+
def self.call(env)
|
5
|
+
request = Rack::Request.new(env)
|
6
|
+
[200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ["HELLO #{request.session[:sso][:email]}"] ]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "Hancock::Client::MockMiddleware" do
|
11
|
+
def app
|
12
|
+
@app = Rack::Builder.new do
|
13
|
+
use Hancock::Client::MockMiddleware do |sso|
|
14
|
+
sso.sso_url = 'http://localhost:20000'
|
15
|
+
end
|
16
|
+
map '/' do
|
17
|
+
run MyMockApp
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
it "should have a valid users logged in" do
|
22
|
+
get '/'
|
23
|
+
last_response.body.should match(/^HELLO \w{3,12}@example.com$/)
|
24
|
+
last_response.status.should eql(200)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Hancock::Client::Default.exclude_paths=" do
|
4
|
+
def app
|
5
|
+
@app = Rack::Builder.new do
|
6
|
+
use Hancock::Client::Middleware do |sso|
|
7
|
+
sso.sso_url = 'http://localhost:20000'
|
8
|
+
sso.exclude_paths = %w(/foo/bar /api/tokenz)
|
9
|
+
end
|
10
|
+
map '/' do
|
11
|
+
run Proc.new {|env| [200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ['HELLO']] }
|
12
|
+
end
|
13
|
+
map '/api/tokenz' do
|
14
|
+
run Proc.new {|env| [200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ['HELLO']] }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
it "should exclude the specified path" do
|
19
|
+
get '/api/tokenz'
|
20
|
+
last_response.status.should eql(200)
|
21
|
+
end
|
22
|
+
it "should exclude the specified path given query parameters" do
|
23
|
+
get '/api/tokenz?foo=bar'
|
24
|
+
last_response.status.should eql(200)
|
25
|
+
end
|
26
|
+
it "should exclude the specified path at a nested level" do
|
27
|
+
get '/api/tokenz/foo/bar/'
|
28
|
+
last_response.status.should eql(302)
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,30 +1,19 @@
|
|
1
|
-
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
-
require 'rubygems'
|
3
1
|
require 'pp'
|
2
|
+
require 'rubygems'
|
4
3
|
gem 'rspec', '~>1.2.0'
|
5
4
|
require 'spec'
|
6
|
-
gem 'webrat', '~>0.4.
|
5
|
+
gem 'webrat', '~>0.4.4'
|
7
6
|
require 'webrat'
|
8
7
|
require 'dm-sweatshop'
|
9
8
|
|
10
|
-
|
11
|
-
gem 'rack-test', '~>0.3.0'
|
9
|
+
gem 'rack-test', '~>0.4.0'
|
12
10
|
require 'rack/test'
|
13
11
|
|
14
|
-
require 'hancock-client'
|
12
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'hancock-client')
|
13
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'hancock-client', 'mock_middleware')
|
15
14
|
|
16
15
|
Spec::Runner.configure do |config|
|
17
16
|
config.include(Rack::Test::Methods)
|
18
17
|
config.include(Webrat::Methods)
|
19
18
|
config.include(Webrat::Matchers)
|
20
|
-
def app
|
21
|
-
@app = Rack::Builder.new do
|
22
|
-
use Hancock::Client::Default do |sso|
|
23
|
-
sso.sso_url = 'http://localhost:20000'
|
24
|
-
end
|
25
|
-
map '/' do
|
26
|
-
run Proc.new {|env| [200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ['HELLO']] }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
19
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hancock-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Corey Donohoe
|
@@ -9,7 +9,7 @@ autorequire: hancock-client
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-07-04 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,16 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 2.0.9
|
44
44
|
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: rack-openid
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0.2"
|
54
|
+
version:
|
45
55
|
description: Hancock SSO rack middleware written in sinatra
|
46
56
|
email:
|
47
57
|
- atmos@atmos.org
|
@@ -57,13 +67,17 @@ files:
|
|
57
67
|
- LICENSE
|
58
68
|
- README.md
|
59
69
|
- Rakefile
|
70
|
+
- lib/hancock-client
|
71
|
+
- lib/hancock-client/default.rb
|
72
|
+
- lib/hancock-client/helpers
|
73
|
+
- lib/hancock-client/helpers/rack.rb
|
74
|
+
- lib/hancock-client/middleware.rb
|
75
|
+
- lib/hancock-client/mock_middleware.rb
|
76
|
+
- lib/hancock-client/sso.rb
|
60
77
|
- lib/hancock-client.rb
|
61
|
-
- lib/rack-openid.rb
|
62
|
-
- lib/sinatra
|
63
|
-
- lib/sinatra/hancock
|
64
|
-
- lib/sinatra/hancock/mock.rb
|
65
|
-
- lib/sinatra/hancock/sso.rb
|
66
78
|
- spec/hancock_sinatra_spec.rb
|
79
|
+
- spec/mock_sso_user_spec.rb
|
80
|
+
- spec/pattern_exclusion_spec.rb
|
67
81
|
- spec/spec_helper.rb
|
68
82
|
has_rdoc: true
|
69
83
|
homepage: http://github.com/atmos/hancock-client
|
data/lib/rack-openid.rb
DELETED
@@ -1,195 +0,0 @@
|
|
1
|
-
require 'openid'
|
2
|
-
require 'openid/consumer'
|
3
|
-
require 'openid/extensions/sreg'
|
4
|
-
require 'openid/store/filesystem'
|
5
|
-
|
6
|
-
module Rack
|
7
|
-
class OpenID
|
8
|
-
def self.build_header(params = {})
|
9
|
-
value = 'OpenID '
|
10
|
-
value += params.map { |k, v|
|
11
|
-
if v.is_a?(Array)
|
12
|
-
"#{k}=\"#{v.join(',')}\""
|
13
|
-
else
|
14
|
-
"#{k}=\"#{v}\""
|
15
|
-
end
|
16
|
-
}.join(', ')
|
17
|
-
value
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.parse_header(str)
|
21
|
-
params = {}
|
22
|
-
if str =~ /^OpenID/
|
23
|
-
str = str.gsub(/^OpenID /, '')
|
24
|
-
str.split(', ').each { |e|
|
25
|
-
k, v = e.split('=')
|
26
|
-
v.gsub!(/^\"/, '').gsub!(/\"$/, "")
|
27
|
-
v = v.split(',')
|
28
|
-
params[k] = v.length > 1 ? v : v.first
|
29
|
-
}
|
30
|
-
end
|
31
|
-
params
|
32
|
-
end
|
33
|
-
|
34
|
-
class TimeoutResponse
|
35
|
-
include ::OpenID::Consumer::Response
|
36
|
-
STATUS = :failure
|
37
|
-
end
|
38
|
-
|
39
|
-
class MissingResponse
|
40
|
-
include ::OpenID::Consumer::Response
|
41
|
-
STATUS = :missing
|
42
|
-
end
|
43
|
-
|
44
|
-
HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS)
|
45
|
-
|
46
|
-
RESPONSE = "rack.openid.response".freeze
|
47
|
-
AUTHENTICATE_HEADER = "WWW-Authenticate".freeze
|
48
|
-
|
49
|
-
|
50
|
-
def initialize(app, store = nil)
|
51
|
-
@app = app
|
52
|
-
@store = store || ::OpenID::Store::Filesystem.new("tmp/openid")
|
53
|
-
freeze
|
54
|
-
end
|
55
|
-
|
56
|
-
def call(env)
|
57
|
-
req = Rack::Request.new(env)
|
58
|
-
if env["REQUEST_METHOD"] == "GET" && req.GET["openid.mode"]
|
59
|
-
complete_authentication(env)
|
60
|
-
end
|
61
|
-
|
62
|
-
status, headers, body = @app.call(env)
|
63
|
-
|
64
|
-
if status.to_i == 401 && (qs = headers[AUTHENTICATE_HEADER])
|
65
|
-
begin_authentication(env, qs)
|
66
|
-
else
|
67
|
-
[status, headers, body]
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
def begin_authentication(env, qs)
|
73
|
-
req = Rack::Request.new(env)
|
74
|
-
params = self.class.parse_header(qs)
|
75
|
-
|
76
|
-
unless session = env["rack.session"]
|
77
|
-
raise RuntimeError, "Rack::OpenID requires a session"
|
78
|
-
end
|
79
|
-
|
80
|
-
consumer = ::OpenID::Consumer.new(session, @store)
|
81
|
-
identifier = params["identifier"]
|
82
|
-
|
83
|
-
begin
|
84
|
-
oidreq = consumer.begin(identifier)
|
85
|
-
add_simple_registration_fields(oidreq, params)
|
86
|
-
url = open_id_redirect_url(req, oidreq, params["trust_root"], params["return_to"], params["method"])
|
87
|
-
return redirect_to(url)
|
88
|
-
rescue ::OpenID::OpenIDError, Timeout::Error => e
|
89
|
-
env[RESPONSE] = MissingResponse.new
|
90
|
-
return @app.call(env)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def complete_authentication(env)
|
95
|
-
req = Rack::Request.new(env)
|
96
|
-
|
97
|
-
unless session = env["rack.session"]
|
98
|
-
raise RuntimeError, "Rack::OpenID requires a session"
|
99
|
-
end
|
100
|
-
|
101
|
-
oidresp = timeout_protection_from_identity_server {
|
102
|
-
consumer = ::OpenID::Consumer.new(session, @store)
|
103
|
-
consumer.complete(req.params, req.url)
|
104
|
-
}
|
105
|
-
|
106
|
-
if oidresp.status == :failure
|
107
|
-
raise "Open ID Response is a failure: #{oidresp.inspect}"
|
108
|
-
end
|
109
|
-
|
110
|
-
env[RESPONSE] = oidresp
|
111
|
-
|
112
|
-
if method = req.GET["_method"]
|
113
|
-
method = method.upcase
|
114
|
-
if HTTP_METHODS.include?(method)
|
115
|
-
env["REQUEST_METHOD"] = method
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
query_hash = env["rack.request.query_hash"]
|
120
|
-
query_hash.delete("_method")
|
121
|
-
query_hash.delete_if do |key, value|
|
122
|
-
key =~ /^openid\./
|
123
|
-
end
|
124
|
-
|
125
|
-
env["QUERY_STRING"] = env["rack.request.query_string"] =
|
126
|
-
Rack::Utils.build_query(env["rack.request.query_hash"])
|
127
|
-
|
128
|
-
request_uri = env["PATH_INFO"]
|
129
|
-
if env["QUERY_STRING"].any?
|
130
|
-
request_uri << "?" + env["QUERY_STRING"]
|
131
|
-
end
|
132
|
-
env["REQUEST_URI"] = request_uri
|
133
|
-
end
|
134
|
-
|
135
|
-
def realm_url(req)
|
136
|
-
url = req.scheme + "://"
|
137
|
-
url << req.host
|
138
|
-
|
139
|
-
if req.scheme == "https" && req.port != 443 ||
|
140
|
-
req.scheme == "http" && req.port != 80
|
141
|
-
url << ":#{req.port}"
|
142
|
-
end
|
143
|
-
|
144
|
-
url
|
145
|
-
end
|
146
|
-
|
147
|
-
def request_url(req)
|
148
|
-
url = realm_url(req)
|
149
|
-
url << req.script_name
|
150
|
-
url << req.path_info
|
151
|
-
url
|
152
|
-
end
|
153
|
-
|
154
|
-
def redirect_to(url)
|
155
|
-
[303, {"Content-Type" => "text/html", "Location" => url}, []]
|
156
|
-
end
|
157
|
-
|
158
|
-
def open_id_redirect_url(req, oidreq, trust_root = nil, return_to = nil, method = nil)
|
159
|
-
if return_to
|
160
|
-
method ||= "get"
|
161
|
-
else
|
162
|
-
return_to = request_url(req)
|
163
|
-
method ||= req.request_method
|
164
|
-
end
|
165
|
-
|
166
|
-
method = method.to_s.downcase
|
167
|
-
oidreq.return_to_args['_method'] = method unless method == "get"
|
168
|
-
oidreq.redirect_url(trust_root || realm_url(req), return_to || request_url(req))
|
169
|
-
end
|
170
|
-
|
171
|
-
def add_simple_registration_fields(oidreq, fields)
|
172
|
-
sregreq = ::OpenID::SReg::Request.new
|
173
|
-
|
174
|
-
if required = fields["required"]
|
175
|
-
sregreq.request_fields(Array(required), true)
|
176
|
-
end
|
177
|
-
|
178
|
-
if optional = fields["optional"]
|
179
|
-
sregreq.request_fields(Array(optional), false)
|
180
|
-
end
|
181
|
-
|
182
|
-
if policy_url = fields["policy_url"]
|
183
|
-
sregreq.policy_url = policy_url
|
184
|
-
end
|
185
|
-
|
186
|
-
oidreq.add_extension(sregreq)
|
187
|
-
end
|
188
|
-
|
189
|
-
def timeout_protection_from_identity_server
|
190
|
-
yield
|
191
|
-
rescue Timeout::Error
|
192
|
-
TimeoutResponse.new
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
data/lib/sinatra/hancock/mock.rb
DELETED
File without changes
|