passage 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +153 -0
- data/bin/passage +51 -42
- data/config.ru +1 -0
- data/ids.yml.example +6 -3
- data/lib/passage.rb +12 -0
- data/lib/passage/app.rb +21 -84
- data/lib/passage/auth/pass_phrase/pass_phrase.rb +45 -0
- data/lib/passage/auth/pass_through/pass_through.rb +19 -0
- data/lib/passage/environment.rb +40 -0
- data/lib/passage/identities.rb +38 -0
- data/lib/passage/open_id.rb +55 -0
- data/lib/passage/version.rb +1 -1
- data/test/test_identities.rb +45 -0
- data/test/teststrap.rb +7 -0
- data/views/identity.erb +10 -0
- metadata +34 -28
- data/README.rdoc +0 -19
- data/test/helper.rb +0 -17
- data/test/test_passage.rb +0 -7
data/README.md
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
passage
|
2
|
+
=======
|
3
|
+
|
4
|
+
Passage is an OpenID provider, which can serve several goals:
|
5
|
+
|
6
|
+
* Personal, tiny-smart-hackable, OpenID provider.
|
7
|
+
* OpenID provider test server.
|
8
|
+
|
9
|
+
Passage aims to provide a 'path through', it can be useful if any or several of these are true for you:
|
10
|
+
|
11
|
+
* You have an internal / sandboxed / restricted environment, as a test server
|
12
|
+
* You don't really care about providing your real ID to a web site.
|
13
|
+
* You wish to remain completely anonymous.
|
14
|
+
* You wish to implement your own authentication strategy (finger print, cell call)
|
15
|
+
* You wish to have full control over your identity and registration detail
|
16
|
+
* You want several identities
|
17
|
+
* .. The list goes on..
|
18
|
+
|
19
|
+
Quick Start
|
20
|
+
-----------
|
21
|
+
|
22
|
+
As a personal gem:
|
23
|
+
|
24
|
+
$gem install passage
|
25
|
+
$passage --ids myids.yml --auth pass_through
|
26
|
+
|
27
|
+
Or deploy it:
|
28
|
+
|
29
|
+
$git clone https://github.com/jondot/passage
|
30
|
+
$export PSG_IDS_FILE=myids.yml
|
31
|
+
$cd passage
|
32
|
+
$rackup
|
33
|
+
|
34
|
+
|
35
|
+
Thats it!
|
36
|
+
|
37
|
+
|
38
|
+
Your identities (`identities.yml`)
|
39
|
+
----------------------------------
|
40
|
+
$cat identities.yml.example
|
41
|
+
'http://localhost:9292/ids/foo':
|
42
|
+
email: foo@foo.org
|
43
|
+
'http://77.127.240.49:9292/ids/foo':
|
44
|
+
email: foo@foo.org
|
45
|
+
'http://77.124.212.222:4567/ids/pookie':
|
46
|
+
email: goo@goo.org
|
47
|
+
!ruby/regexp /http:\/\/localhost:4567\/ids\/(.*)/:
|
48
|
+
email: '#{$1}@foo.org'
|
49
|
+
nickname: '#{$1}'
|
50
|
+
|
51
|
+
The one starting with `!ruby/regexp` is a proper regular expression with a capture group. The OpenID SReg fields following it (email, nickname), are using the capture group in order to have some kind of logic in them, without your intervention. You can identify these as being plain ruby interpolated strings.
|
52
|
+
For further interest, you can read below about typical use cases for setting up identities.
|
53
|
+
|
54
|
+
Authentication Strategies
|
55
|
+
-------------------------
|
56
|
+
|
57
|
+
the `auth` folder holds _authentication strategies_. An authentication strategy answers to the following:
|
58
|
+
|
59
|
+
def auth_setup(req); end
|
60
|
+
def auth_fetch; end
|
61
|
+
def auth_validate!(identity, trust_root); end
|
62
|
+
|
63
|
+
A good starting point will be to copy-paste an existing one and tweak it to your use.
|
64
|
+
Authentication strategies are **auto-discovered**, so just drop your folder in `/auth`, and configure your selected one via configuration.
|
65
|
+
An example authentication strategy would be one that would present a user/password form and store credentials at the DB. This will "upgrade" your Passage instance from a _personal_ to a full fledged OpenID server.
|
66
|
+
|
67
|
+
Here is a description of existing authentication strategies
|
68
|
+
|
69
|
+
* `pass_through` - Lets authentication always pass. No need for any credentials or so.
|
70
|
+
* `pass_phrase` - Authentication will pass only if a proper pass phrase was specified.
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
Configuration
|
75
|
+
-------------
|
76
|
+
You can pass an options hash to Passage:
|
77
|
+
|
78
|
+
Passage::App.configure! options
|
79
|
+
|
80
|
+
In it, these are the available configurations:
|
81
|
+
|
82
|
+
* `:ids_file` - location of the identities.yml file.
|
83
|
+
* `:auth` - selected authentication strategy.
|
84
|
+
* `:logger` - a logger instance
|
85
|
+
|
86
|
+
When under certain hosting providers, Passage knows to take important configuration values from your environment variables instead, by convention, these will be PSG_[uppercase config key], e.g. `PSG_IDS_FILE`.
|
87
|
+
|
88
|
+
For specifying configurations via command line run `$passage --help`
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
As a Personal OpenID Provider
|
94
|
+
-----------------------------
|
95
|
+
You can have your fixed identities at your domain, or even throw-away identities.
|
96
|
+
|
97
|
+
To set fixed identities in your domain, simply code them up in your `identities.yml` file and let `passage` know about it.
|
98
|
+
|
99
|
+
Using throw-away identities can maximize your anonymity around the Web. To have throw-away identities you can specify any identity you wish in your `identities.yml` manually, or specify a smart rule as a regex identity:
|
100
|
+
|
101
|
+
!ruby/regex /http:\/\/mydomain\.com\/ids\/(.*)/:
|
102
|
+
email: 'myuser@gmail.com'
|
103
|
+
|
104
|
+
This will let you specify any user you wish to make up, at your domain.
|
105
|
+
|
106
|
+
As an OpenID Test Server
|
107
|
+
------------------------
|
108
|
+
Passage is great (and being used internally) for integration tests against OpenID consumers (relying parties).
|
109
|
+
Through Passage's identity configuration system, you can load up fixed identities per test scenario, or you can load identities which follow certain rules (with regex enabled identities).
|
110
|
+
|
111
|
+
As an example, you can store as fixed identities in your `dev` environment:
|
112
|
+
|
113
|
+
'http://dev.com/ids/foo':
|
114
|
+
email: foo@dev.com
|
115
|
+
|
116
|
+
Or, you can store the following if you have many dynamic users:
|
117
|
+
|
118
|
+
!ruby/regex /http:\/\/dev\.com\/ids\/(.*)/:
|
119
|
+
email: '#{$1}@dev.com'
|
120
|
+
|
121
|
+
This makes use of regex enabled identities, in which you specify a regex as the user identifier, and any SReg property can make use of the captures that were made.
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
Hacking
|
126
|
+
-------
|
127
|
+
|
128
|
+
But this is not the end. Passage is extremely flexible, and you can get a good mileage out of it. To your benefit, I've devided the points of interest into the following:
|
129
|
+
|
130
|
+
* app - any application specific flow; you'll seldom want to touch this.
|
131
|
+
* environment - any application configuration and environment setups.
|
132
|
+
* open_id - any openid related logic; you might want to fiddle with this in order to add PAPE for example.
|
133
|
+
* identities - the basic logic for identity matching; you might want to play with this in order to have random identities, for example.
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
Contributing to passage
|
138
|
+
=======================
|
139
|
+
|
140
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
141
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
142
|
+
* Fork the project
|
143
|
+
* Start a feature/bugfix branch
|
144
|
+
* Commit and push until you are happy with your contribution
|
145
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
146
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
147
|
+
|
148
|
+
Copyright
|
149
|
+
=========
|
150
|
+
|
151
|
+
Copyright (c) 2011 Dotan Nahum. See LICENSE.txt for
|
152
|
+
further details.
|
153
|
+
|
data/bin/passage
CHANGED
@@ -1,42 +1,51 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
opts.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
opts.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
help = <<HELP
|
6
|
+
Passage is your personal tweakable OpenID provider.
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
passage [OPTIONS]
|
10
|
+
|
11
|
+
Options:
|
12
|
+
HELP
|
13
|
+
|
14
|
+
|
15
|
+
require 'optparse'
|
16
|
+
require 'passage'
|
17
|
+
|
18
|
+
exec = {}
|
19
|
+
options = {}
|
20
|
+
|
21
|
+
opts = OptionParser.new do |opts|
|
22
|
+
opts.banner = help
|
23
|
+
|
24
|
+
opts.on("--ids [IDSFILE]", "Configuration file for identities (yaml).") do |c|
|
25
|
+
options[:ids_file] = c
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("--auth [AUTH]", "Authentication strategy use_snake_case e.g. pass_through") do |c|
|
29
|
+
options[:auth] = c
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
opts.on("--version", "Display current version.") do
|
34
|
+
puts "Passage v" + Passage::VERSION
|
35
|
+
exit 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
opts.parse!
|
41
|
+
rescue OptionParser::InvalidOption
|
42
|
+
puts "passage: #{$!.message}"
|
43
|
+
puts "passage: try 'passage --help' for more information"
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
require 'passage/app'
|
48
|
+
|
49
|
+
Passage::App.configure! options
|
50
|
+
Passage::App.run!(options)
|
51
|
+
|
data/config.ru
CHANGED
data/ids.yml.example
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
'http://localhost:9292/foo':
|
1
|
+
'http://localhost:9292/ids/foo':
|
2
2
|
email: foo@foo.org
|
3
|
-
'http://77.127.
|
3
|
+
'http://77.127.240.49:9292/ids/foo':
|
4
4
|
email: foo@foo.org
|
5
|
-
'http://77.124.212.222:4567/pookie':
|
5
|
+
'http://77.124.212.222:4567/ids/pookie':
|
6
6
|
email: goo@goo.org
|
7
|
+
!ruby/regexp /http:\/\/localhost:4567\/ids\/(.*)/:
|
8
|
+
email: '#{$1}@foo.org'
|
9
|
+
nickname: '#{$1}'
|
7
10
|
|
data/lib/passage.rb
CHANGED
@@ -1 +1,13 @@
|
|
1
|
+
require 'openid'
|
2
|
+
require 'openid/extensions/sreg'
|
3
|
+
require 'openid/extensions/pape'
|
4
|
+
require 'openid/store/filesystem'
|
5
|
+
require 'openid/consumer/discovery'
|
6
|
+
|
7
|
+
require 'passage/environment'
|
8
|
+
require 'passage/open_id'
|
1
9
|
require 'passage/version'
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
data/lib/passage/app.rb
CHANGED
@@ -1,111 +1,48 @@
|
|
1
|
-
require 'sinatra/
|
2
|
-
require 'openid'
|
3
|
-
require 'openid/consumer/discovery'
|
4
|
-
require 'openid/extensions/sreg'
|
5
|
-
require 'openid/extensions/pape'
|
6
|
-
require 'openid/store/filesystem'
|
7
|
-
require 'yaml'
|
1
|
+
require 'sinatra/base'
|
8
2
|
|
9
3
|
module Passage
|
10
4
|
class App < Sinatra::Base
|
11
|
-
|
5
|
+
set :views, File.expand_path('../../views', File.dirname(__FILE__))
|
6
|
+
|
7
|
+
alias_method :app, :options
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
set :logging, true
|
16
|
-
configure(:development) do
|
17
|
-
register Sinatra::Reloader
|
18
|
-
end
|
9
|
+
register Passage::Environment
|
10
|
+
helpers Passage::OpenIDHelpers
|
19
11
|
|
20
12
|
[:post, :get].each do |meth|
|
21
13
|
send meth, '/' do
|
22
|
-
|
14
|
+
|
15
|
+
oidreq = nil
|
16
|
+
begin
|
17
|
+
oidreq = server.decode_request(params) || auth_fetch
|
18
|
+
rescue ProtocolError => e
|
19
|
+
end
|
20
|
+
|
23
21
|
return "This is an OpenID server endpoint." unless oidreq
|
24
22
|
|
25
23
|
oidresp = nil
|
26
24
|
if oidreq.kind_of?(CheckIDRequest)
|
27
|
-
|
25
|
+
auth_setup(oidreq)
|
28
26
|
|
29
27
|
identity = oidreq.identity
|
30
|
-
|
31
|
-
|
28
|
+
auth_validate!(identity, oidreq.trust_root)
|
29
|
+
|
30
|
+
oidresp = openid_positive_assertion(oidreq, identity, app.identities[identity])
|
32
31
|
else
|
33
32
|
oidresp = server.handle_request(oidreq)
|
34
33
|
end
|
35
34
|
|
36
|
-
|
35
|
+
openid_response(oidresp)
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
|
-
get '/:identity' do
|
39
|
+
get '/ids/:identity' do
|
41
40
|
@identity = params[:identity]
|
42
41
|
@endpoint = server_url
|
43
42
|
erb :identity
|
44
43
|
end
|
45
44
|
|
46
|
-
private
|
47
|
-
def must_be_authorized!(id, root)
|
48
|
-
true
|
49
|
-
end
|
50
|
-
|
51
|
-
def add_sreg(oidreq, oidresp, identity)
|
52
|
-
sregreq = OpenID::SReg::Request.from_openid_request(oidreq)
|
53
|
-
return if sregreq.nil?
|
54
|
-
|
55
|
-
ym = YAML::load_file(settings.ids_file)
|
56
|
-
return if ym.nil? || ym[identity].nil?
|
57
|
-
|
58
|
-
puts "** sending out #{ym[identity]}" # todo: proper log
|
59
|
-
|
60
|
-
sregresp = OpenID::SReg::Response.extract_response(sregreq, ym[identity])
|
61
|
-
oidresp.add_extension(sregresp)
|
62
|
-
end
|
63
|
-
|
64
|
-
def create_positive_assertion(oidreq, identity)
|
65
|
-
oidresp = oidreq.answer(true, nil, identity)
|
66
|
-
add_sreg(oidreq, oidresp, identity)
|
67
|
-
oidresp
|
68
|
-
end
|
69
|
-
|
70
|
-
def get_oid_from_params_or_session(params)
|
71
|
-
begin
|
72
|
-
oidreq = server.decode_request(params)
|
73
|
-
rescue ProtocolError => e
|
74
|
-
oidreq = session[CHECK_ID_REQ_K]
|
75
|
-
session[CHECK_ID_REQ_K] = nil
|
76
|
-
end
|
77
|
-
oidreq
|
78
|
-
end
|
79
|
-
|
80
|
-
def use_when_not_authorized(oidreq)
|
81
|
-
session[CHECK_ID_REQ_K] = oidreq
|
82
|
-
end
|
83
|
-
|
84
|
-
def handle_response(oidresp)
|
85
|
-
if oidresp.needs_signing
|
86
|
-
signed_response = server.signatory.sign(oidresp)
|
87
|
-
end
|
88
|
-
web_response = server.encode_response(oidresp)
|
89
|
-
|
90
|
-
case web_response.code
|
91
|
-
when HTTP_REDIRECT
|
92
|
-
redirect web_response.headers['location']
|
93
|
-
else
|
94
|
-
web_response.body
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def server
|
99
|
-
if @server.nil?
|
100
|
-
dir = Pathname.new(".").join('db').join('openid-store')
|
101
|
-
store = OpenID::Store::Filesystem.new(dir)
|
102
|
-
@server = Server.new(store, server_url)
|
103
|
-
end
|
104
|
-
return @server
|
105
|
-
end
|
106
|
-
|
107
|
-
def server_url
|
108
|
-
"#{request.scheme}://#{request.host}:#{request.port}/"
|
109
|
-
end
|
110
45
|
end
|
111
46
|
end
|
47
|
+
|
48
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Passage
|
4
|
+
module Auth
|
5
|
+
module PassPhrase
|
6
|
+
module Helpers
|
7
|
+
CK = '__phrase_ck'
|
8
|
+
|
9
|
+
def auth_setup(req)
|
10
|
+
session[CK] = req
|
11
|
+
end
|
12
|
+
|
13
|
+
def auth_fetch
|
14
|
+
session[CK]
|
15
|
+
end
|
16
|
+
|
17
|
+
def auth_validate!(identity, trust_root)
|
18
|
+
redirect '/login' unless session[:authorized]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.registered(app)
|
23
|
+
app.helpers Helpers
|
24
|
+
|
25
|
+
app.get '/login' do
|
26
|
+
"<form method='POST' action='/login'>" +
|
27
|
+
"Your pass phrase<br/><input type='text' name='phrase'>" +
|
28
|
+
"<input type='submit'/></form>"
|
29
|
+
end
|
30
|
+
|
31
|
+
app.post '/login' do
|
32
|
+
if params[:phrase] == 'foo'
|
33
|
+
session[:authorized] = true
|
34
|
+
redirect '/'
|
35
|
+
else
|
36
|
+
session[:authorized] = nil
|
37
|
+
redirect '/login'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Sinatra.register PassPhrase
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
module Passage
|
3
|
+
module Auth
|
4
|
+
module PassThrough
|
5
|
+
module Helpers
|
6
|
+
def auth_setup(req); end
|
7
|
+
def auth_fetch; end
|
8
|
+
def auth_validate!(identity, trust_root); end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.registered(app)
|
12
|
+
app.helpers Auth::PassThrough::Helpers
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Sinatra.register PassThrough
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'logger'
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'passage/identities'
|
5
|
+
|
6
|
+
module Passage
|
7
|
+
module Environment
|
8
|
+
def configure!(opts)
|
9
|
+
opts[:auth] ||= :pass_through
|
10
|
+
|
11
|
+
set :sessions, true
|
12
|
+
set :log, opts[:logger] || Logger.new(STDOUT)
|
13
|
+
|
14
|
+
# load identities
|
15
|
+
if(opts[:ids_file])
|
16
|
+
ids = Identities.new YAML::load_file(opts[:ids_file] || ENV['PSG_IDS_FILE'] )
|
17
|
+
set :identities, ids
|
18
|
+
log.info "loaded #{ids.count} identities from #{opts[:ids_file]}"
|
19
|
+
else
|
20
|
+
set :identities, {}
|
21
|
+
log.info "no identities loaded (free for all)"
|
22
|
+
end
|
23
|
+
|
24
|
+
# load auth
|
25
|
+
Dir.glob(File.expand_path("auth/**/*.rb", File.dirname(__FILE__))).each do |f|
|
26
|
+
require f
|
27
|
+
log.debug "discovered auth: #{File.basename(f)[0..-4]}"
|
28
|
+
end
|
29
|
+
register constantize(opts[:auth] || ENV['PSG_AUTH'])
|
30
|
+
log.info "loaded #{opts[:auth] || ENV['PSG_AUTH']} authentication"
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def constantize(word)
|
35
|
+
Passage::Auth::const_get(word.to_s.gsub(/(?:^|_)(.)/) { $1.upcase })
|
36
|
+
end
|
37
|
+
|
38
|
+
Sinatra.register Environment
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Identities
|
2
|
+
def initialize(hash)
|
3
|
+
@regex = {}
|
4
|
+
@hash = {}
|
5
|
+
hash.keys.each do |k|
|
6
|
+
if k.is_a? Regexp
|
7
|
+
@regex[k] = hash[k]
|
8
|
+
else
|
9
|
+
@hash[k] = hash[k]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](index)
|
15
|
+
@hash[index] || regex_lookup(index)
|
16
|
+
end
|
17
|
+
|
18
|
+
def count
|
19
|
+
@hash.keys.count + @regex.keys.count
|
20
|
+
end
|
21
|
+
private
|
22
|
+
def regex_lookup(index)
|
23
|
+
@regex.keys.each do |k|
|
24
|
+
if index =~ k
|
25
|
+
subj = @regex[k]
|
26
|
+
if(subj.respond_to? :merge)
|
27
|
+
return subj.dup.merge(subj) { |k,v| eval("\"#{v}\"") }
|
28
|
+
elsif(subj.respond_to? :map)
|
29
|
+
return subj.map { |e| eval("\"#{v}\"") }
|
30
|
+
else
|
31
|
+
return eval("\"#{v}\"")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Passage
|
4
|
+
module OpenIDHelpers
|
5
|
+
include ::OpenID::Server
|
6
|
+
|
7
|
+
def openid_positive_assertion(oidreq, identity, details)
|
8
|
+
oidresp = oidreq.answer(true, nil, identity)
|
9
|
+
add_sreg(oidreq, oidresp, identity, details)
|
10
|
+
oidresp
|
11
|
+
end
|
12
|
+
|
13
|
+
def openid_response(oidresp)
|
14
|
+
if oidresp.needs_signing
|
15
|
+
signed_response = server.signatory.sign(oidresp)
|
16
|
+
end
|
17
|
+
web_response = server.encode_response(oidresp)
|
18
|
+
|
19
|
+
case web_response.code
|
20
|
+
when HTTP_REDIRECT
|
21
|
+
redirect web_response.headers['location']
|
22
|
+
else
|
23
|
+
web_response.body
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def server
|
28
|
+
if @server.nil?
|
29
|
+
dir = Pathname.new(".").join('db').join('openid-store')
|
30
|
+
store = OpenID::Store::Filesystem.new(dir)
|
31
|
+
@server = Server.new(store, server_url)
|
32
|
+
end
|
33
|
+
return @server
|
34
|
+
end
|
35
|
+
|
36
|
+
def server_url
|
37
|
+
"#{request.scheme}://#{request.host}:#{request.port}/"
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def add_sreg(oidreq, oidresp, identity, details)
|
42
|
+
return if details.nil?
|
43
|
+
sregreq = OpenID::SReg::Request.from_openid_request(oidreq)
|
44
|
+
return if sregreq.nil?
|
45
|
+
p details
|
46
|
+
sregresp = OpenID::SReg::Response.extract_response(sregreq, details)
|
47
|
+
oidresp.add_extension(sregresp)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
Sinatra.helpers OpenIDHelpers
|
54
|
+
end
|
55
|
+
|
data/lib/passage/version.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
require 'passage/identities'
|
3
|
+
|
4
|
+
context "when using identities, " do
|
5
|
+
setup do
|
6
|
+
h = {
|
7
|
+
/http:\/\/(.*)\.org\/(.*)/ => { :email => 'joe@#{$1}.com', :phone => '972-#{$2}'},
|
8
|
+
"http://localhost/ids/johnnyb" => { :email => 'joe@#{$1}.com'}
|
9
|
+
}
|
10
|
+
Identities.new h
|
11
|
+
end
|
12
|
+
|
13
|
+
context "given regex identities" do
|
14
|
+
asserts("that capture interpolation"){ topic["http://google.org/555-1234"][:email] }.equals "joe@google.com"
|
15
|
+
asserts("that capture interpolation does'nt overwrite config and still"){ topic["http://google.org/555-1234"][:email] }.equals "joe@google.com"
|
16
|
+
|
17
|
+
asserts("that capture group 2 (phone number)"){ topic["http://google.org/555-1234"][:phone] }.equals "972-555-1234"
|
18
|
+
end
|
19
|
+
|
20
|
+
context "given normal identities" do
|
21
|
+
asserts("email"){ topic["http://localhost/ids/johnnyb"][:email] }.equals 'joe@#{$1}.com'
|
22
|
+
end
|
23
|
+
|
24
|
+
context "given no match found" do
|
25
|
+
asserts("identity"){topic["foo"]}.nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when loading identities from file, " do
|
30
|
+
setup do
|
31
|
+
Identities.new YAML::load_file 'integration.yml'
|
32
|
+
end
|
33
|
+
context "given regex identities" do
|
34
|
+
asserts("that email"){ topic["http://localhost:4567/ids/joe"]['email'] }.equals "joe@foo.org"
|
35
|
+
asserts("that nickname"){ topic["http://localhost:4567/ids/joe"]['nickname'] }.equals "joe"
|
36
|
+
end
|
37
|
+
|
38
|
+
context "given normal identities" do
|
39
|
+
asserts("email"){ topic["http://77.127.240.49:9292/ids/foo"]['email'] }.equals 'foo@foo.org'
|
40
|
+
end
|
41
|
+
|
42
|
+
context "given no match found" do
|
43
|
+
asserts("identity"){topic["foo"]}.nil
|
44
|
+
end
|
45
|
+
end
|
data/test/teststrap.rb
ADDED
data/views/identity.erb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dotan Nahum
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-03-
|
18
|
+
date: 2011-03-29 00:00:00 +02:00
|
19
19
|
default_executable: passage
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -46,25 +46,11 @@ dependencies:
|
|
46
46
|
- 0
|
47
47
|
version: "0"
|
48
48
|
requirement: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
type: :runtime
|
51
|
-
prerelease: false
|
52
|
-
name: sinatra-reloader
|
53
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
54
|
-
none: false
|
55
|
-
requirements:
|
56
|
-
- - ">="
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
hash: 3
|
59
|
-
segments:
|
60
|
-
- 0
|
61
|
-
version: "0"
|
62
|
-
requirement: *id003
|
63
49
|
- !ruby/object:Gem::Dependency
|
64
50
|
type: :development
|
65
51
|
prerelease: false
|
66
52
|
name: bundler
|
67
|
-
version_requirements: &
|
53
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
68
54
|
none: false
|
69
55
|
requirements:
|
70
56
|
- - ~>
|
@@ -75,12 +61,12 @@ dependencies:
|
|
75
61
|
- 0
|
76
62
|
- 0
|
77
63
|
version: 1.0.0
|
78
|
-
requirement: *
|
64
|
+
requirement: *id003
|
79
65
|
- !ruby/object:Gem::Dependency
|
80
66
|
type: :development
|
81
67
|
prerelease: false
|
82
68
|
name: jeweler
|
83
|
-
version_requirements: &
|
69
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
84
70
|
none: false
|
85
71
|
requirements:
|
86
72
|
- - ~>
|
@@ -91,11 +77,25 @@ dependencies:
|
|
91
77
|
- 5
|
92
78
|
- 2
|
93
79
|
version: 1.5.2
|
94
|
-
requirement: *
|
80
|
+
requirement: *id004
|
95
81
|
- !ruby/object:Gem::Dependency
|
96
82
|
type: :development
|
97
83
|
prerelease: false
|
98
84
|
name: rcov
|
85
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirement: *id005
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
name: sinatra-reloader
|
99
99
|
version_requirements: &id006 !ruby/object:Gem::Requirement
|
100
100
|
none: false
|
101
101
|
requirements:
|
@@ -114,17 +114,23 @@ extensions: []
|
|
114
114
|
|
115
115
|
extra_rdoc_files:
|
116
116
|
- LICENSE.txt
|
117
|
-
- README.
|
117
|
+
- README.md
|
118
118
|
files:
|
119
119
|
- config.ru
|
120
120
|
- ids.yml.example
|
121
121
|
- lib/passage.rb
|
122
122
|
- lib/passage/app.rb
|
123
|
+
- lib/passage/auth/pass_phrase/pass_phrase.rb
|
124
|
+
- lib/passage/auth/pass_through/pass_through.rb
|
125
|
+
- lib/passage/environment.rb
|
126
|
+
- lib/passage/identities.rb
|
127
|
+
- lib/passage/open_id.rb
|
123
128
|
- lib/passage/version.rb
|
129
|
+
- views/identity.erb
|
124
130
|
- LICENSE.txt
|
125
|
-
- README.
|
126
|
-
- test/
|
127
|
-
- test/
|
131
|
+
- README.md
|
132
|
+
- test/test_identities.rb
|
133
|
+
- test/teststrap.rb
|
128
134
|
- bin/passage
|
129
135
|
has_rdoc: true
|
130
136
|
homepage: http://github.com/jondot/passage
|
@@ -161,5 +167,5 @@ signing_key:
|
|
161
167
|
specification_version: 3
|
162
168
|
summary: Your personal tweakable OpenID server.
|
163
169
|
test_files:
|
164
|
-
- test/
|
165
|
-
- test/
|
170
|
+
- test/test_identities.rb
|
171
|
+
- test/teststrap.rb
|
data/README.rdoc
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
= passage
|
2
|
-
|
3
|
-
Description goes here.
|
4
|
-
|
5
|
-
== Contributing to passage
|
6
|
-
|
7
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
-
* Fork the project
|
10
|
-
* Start a feature/bugfix branch
|
11
|
-
* Commit and push until you are happy with your contribution
|
12
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
-
|
15
|
-
== Copyright
|
16
|
-
|
17
|
-
Copyright (c) 2011 Dotan Nahum. See LICENSE.txt for
|
18
|
-
further details.
|
19
|
-
|
data/test/helper.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'test/unit'
|
11
|
-
|
12
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
13
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
-
require 'passage'
|
15
|
-
|
16
|
-
class Test::Unit::TestCase
|
17
|
-
end
|