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