##// END OF EJS Templates
Prevent 500 error on login when there's a typo in OpenID URI scheme, such as http;// or http.//...
Jean-Baptiste Barth -
r3819:83e4cf3dd420
parent child
Show More
@@ -1,217 +1,224
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'account_controller'
19 require 'account_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class AccountController; def rescue_action(e) raise e end; end
22 class AccountController; def rescue_action(e) raise e end; end
23
23
24 class AccountControllerTest < ActionController::TestCase
24 class AccountControllerTest < ActionController::TestCase
25 fixtures :users, :roles
25 fixtures :users, :roles
26
26
27 def setup
27 def setup
28 @controller = AccountController.new
28 @controller = AccountController.new
29 @request = ActionController::TestRequest.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
30 @response = ActionController::TestResponse.new
31 User.current = nil
31 User.current = nil
32 end
32 end
33
33
34 def test_login_should_redirect_to_back_url_param
34 def test_login_should_redirect_to_back_url_param
35 # request.uri is "test.host" in test environment
35 # request.uri is "test.host" in test environment
36 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.host%2Fissues%2Fshow%2F1'
36 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.host%2Fissues%2Fshow%2F1'
37 assert_redirected_to '/issues/show/1'
37 assert_redirected_to '/issues/show/1'
38 end
38 end
39
39
40 def test_login_should_not_redirect_to_another_host
40 def test_login_should_not_redirect_to_another_host
41 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.foo%2Ffake'
41 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.foo%2Ffake'
42 assert_redirected_to '/my/page'
42 assert_redirected_to '/my/page'
43 end
43 end
44
44
45 def test_login_with_wrong_password
45 def test_login_with_wrong_password
46 post :login, :username => 'admin', :password => 'bad'
46 post :login, :username => 'admin', :password => 'bad'
47 assert_response :success
47 assert_response :success
48 assert_template 'login'
48 assert_template 'login'
49 assert_tag 'div',
49 assert_tag 'div',
50 :attributes => { :class => "flash error" },
50 :attributes => { :class => "flash error" },
51 :content => /Invalid user or password/
51 :content => /Invalid user or password/
52 end
52 end
53
53
54 if Object.const_defined?(:OpenID)
54 if Object.const_defined?(:OpenID)
55
55
56 def test_login_with_openid_for_existing_user
56 def test_login_with_openid_for_existing_user
57 Setting.self_registration = '3'
57 Setting.self_registration = '3'
58 Setting.openid = '1'
58 Setting.openid = '1'
59 existing_user = User.new(:firstname => 'Cool',
59 existing_user = User.new(:firstname => 'Cool',
60 :lastname => 'User',
60 :lastname => 'User',
61 :mail => 'user@somedomain.com',
61 :mail => 'user@somedomain.com',
62 :identity_url => 'http://openid.example.com/good_user')
62 :identity_url => 'http://openid.example.com/good_user')
63 existing_user.login = 'cool_user'
63 existing_user.login = 'cool_user'
64 assert existing_user.save!
64 assert existing_user.save!
65
65
66 post :login, :openid_url => existing_user.identity_url
66 post :login, :openid_url => existing_user.identity_url
67 assert_redirected_to 'my/page'
67 assert_redirected_to 'my/page'
68 end
68 end
69
69
70 def test_login_with_invalid_openid_provider
71 Setting.self_registration = '0'
72 Setting.openid = '1'
73 post :login, :openid_url => 'http;//openid.example.com/good_user'
74 assert_redirected_to home_url
75 end
76
70 def test_login_with_openid_for_existing_non_active_user
77 def test_login_with_openid_for_existing_non_active_user
71 Setting.self_registration = '2'
78 Setting.self_registration = '2'
72 Setting.openid = '1'
79 Setting.openid = '1'
73 existing_user = User.new(:firstname => 'Cool',
80 existing_user = User.new(:firstname => 'Cool',
74 :lastname => 'User',
81 :lastname => 'User',
75 :mail => 'user@somedomain.com',
82 :mail => 'user@somedomain.com',
76 :identity_url => 'http://openid.example.com/good_user',
83 :identity_url => 'http://openid.example.com/good_user',
77 :status => User::STATUS_REGISTERED)
84 :status => User::STATUS_REGISTERED)
78 existing_user.login = 'cool_user'
85 existing_user.login = 'cool_user'
79 assert existing_user.save!
86 assert existing_user.save!
80
87
81 post :login, :openid_url => existing_user.identity_url
88 post :login, :openid_url => existing_user.identity_url
82 assert_redirected_to 'login'
89 assert_redirected_to 'login'
83 end
90 end
84
91
85 def test_login_with_openid_with_new_user_created
92 def test_login_with_openid_with_new_user_created
86 Setting.self_registration = '3'
93 Setting.self_registration = '3'
87 Setting.openid = '1'
94 Setting.openid = '1'
88 post :login, :openid_url => 'http://openid.example.com/good_user'
95 post :login, :openid_url => 'http://openid.example.com/good_user'
89 assert_redirected_to 'my/account'
96 assert_redirected_to 'my/account'
90 user = User.find_by_login('cool_user')
97 user = User.find_by_login('cool_user')
91 assert user
98 assert user
92 assert_equal 'Cool', user.firstname
99 assert_equal 'Cool', user.firstname
93 assert_equal 'User', user.lastname
100 assert_equal 'User', user.lastname
94 end
101 end
95
102
96 def test_login_with_openid_with_new_user_and_self_registration_off
103 def test_login_with_openid_with_new_user_and_self_registration_off
97 Setting.self_registration = '0'
104 Setting.self_registration = '0'
98 Setting.openid = '1'
105 Setting.openid = '1'
99 post :login, :openid_url => 'http://openid.example.com/good_user'
106 post :login, :openid_url => 'http://openid.example.com/good_user'
100 assert_redirected_to home_url
107 assert_redirected_to home_url
101 user = User.find_by_login('cool_user')
108 user = User.find_by_login('cool_user')
102 assert ! user
109 assert ! user
103 end
110 end
104
111
105 def test_login_with_openid_with_new_user_created_with_email_activation_should_have_a_token
112 def test_login_with_openid_with_new_user_created_with_email_activation_should_have_a_token
106 Setting.self_registration = '1'
113 Setting.self_registration = '1'
107 Setting.openid = '1'
114 Setting.openid = '1'
108 post :login, :openid_url => 'http://openid.example.com/good_user'
115 post :login, :openid_url => 'http://openid.example.com/good_user'
109 assert_redirected_to 'login'
116 assert_redirected_to 'login'
110 user = User.find_by_login('cool_user')
117 user = User.find_by_login('cool_user')
111 assert user
118 assert user
112
119
113 token = Token.find_by_user_id_and_action(user.id, 'register')
120 token = Token.find_by_user_id_and_action(user.id, 'register')
114 assert token
121 assert token
115 end
122 end
116
123
117 def test_login_with_openid_with_new_user_created_with_manual_activation
124 def test_login_with_openid_with_new_user_created_with_manual_activation
118 Setting.self_registration = '2'
125 Setting.self_registration = '2'
119 Setting.openid = '1'
126 Setting.openid = '1'
120 post :login, :openid_url => 'http://openid.example.com/good_user'
127 post :login, :openid_url => 'http://openid.example.com/good_user'
121 assert_redirected_to 'login'
128 assert_redirected_to 'login'
122 user = User.find_by_login('cool_user')
129 user = User.find_by_login('cool_user')
123 assert user
130 assert user
124 assert_equal User::STATUS_REGISTERED, user.status
131 assert_equal User::STATUS_REGISTERED, user.status
125 end
132 end
126
133
127 def test_login_with_openid_with_new_user_with_conflict_should_register
134 def test_login_with_openid_with_new_user_with_conflict_should_register
128 Setting.self_registration = '3'
135 Setting.self_registration = '3'
129 Setting.openid = '1'
136 Setting.openid = '1'
130 existing_user = User.new(:firstname => 'Cool', :lastname => 'User', :mail => 'user@somedomain.com')
137 existing_user = User.new(:firstname => 'Cool', :lastname => 'User', :mail => 'user@somedomain.com')
131 existing_user.login = 'cool_user'
138 existing_user.login = 'cool_user'
132 assert existing_user.save!
139 assert existing_user.save!
133
140
134 post :login, :openid_url => 'http://openid.example.com/good_user'
141 post :login, :openid_url => 'http://openid.example.com/good_user'
135 assert_response :success
142 assert_response :success
136 assert_template 'register'
143 assert_template 'register'
137 assert assigns(:user)
144 assert assigns(:user)
138 assert_equal 'http://openid.example.com/good_user', assigns(:user)[:identity_url]
145 assert_equal 'http://openid.example.com/good_user', assigns(:user)[:identity_url]
139 end
146 end
140
147
141 def test_setting_openid_should_return_true_when_set_to_true
148 def test_setting_openid_should_return_true_when_set_to_true
142 Setting.openid = '1'
149 Setting.openid = '1'
143 assert_equal true, Setting.openid?
150 assert_equal true, Setting.openid?
144 end
151 end
145
152
146 else
153 else
147 puts "Skipping openid tests."
154 puts "Skipping openid tests."
148 end
155 end
149
156
150 def test_logout
157 def test_logout
151 @request.session[:user_id] = 2
158 @request.session[:user_id] = 2
152 get :logout
159 get :logout
153 assert_redirected_to ''
160 assert_redirected_to ''
154 assert_nil @request.session[:user_id]
161 assert_nil @request.session[:user_id]
155 end
162 end
156
163
157 context "GET #register" do
164 context "GET #register" do
158 context "with self registration on" do
165 context "with self registration on" do
159 setup do
166 setup do
160 Setting.self_registration = '3'
167 Setting.self_registration = '3'
161 get :register
168 get :register
162 end
169 end
163
170
164 should_respond_with :success
171 should_respond_with :success
165 should_render_template :register
172 should_render_template :register
166 should_assign_to :user
173 should_assign_to :user
167 end
174 end
168
175
169 context "with self registration off" do
176 context "with self registration off" do
170 setup do
177 setup do
171 Setting.self_registration = '0'
178 Setting.self_registration = '0'
172 get :register
179 get :register
173 end
180 end
174
181
175 should_redirect_to('/') { home_url }
182 should_redirect_to('/') { home_url }
176 end
183 end
177 end
184 end
178
185
179 # See integration/account_test.rb for the full test
186 # See integration/account_test.rb for the full test
180 context "POST #register" do
187 context "POST #register" do
181 context "with self registration on automatic" do
188 context "with self registration on automatic" do
182 setup do
189 setup do
183 Setting.self_registration = '3'
190 Setting.self_registration = '3'
184 post :register, :user => {
191 post :register, :user => {
185 :login => 'register',
192 :login => 'register',
186 :password => 'test',
193 :password => 'test',
187 :password_confirmation => 'test',
194 :password_confirmation => 'test',
188 :firstname => 'John',
195 :firstname => 'John',
189 :lastname => 'Doe',
196 :lastname => 'Doe',
190 :mail => 'register@example.com'
197 :mail => 'register@example.com'
191 }
198 }
192 end
199 end
193
200
194 should_respond_with :redirect
201 should_respond_with :redirect
195 should_assign_to :user
202 should_assign_to :user
196 should_redirect_to('my page') { {:controller => 'my', :action => 'account'} }
203 should_redirect_to('my page') { {:controller => 'my', :action => 'account'} }
197
204
198 should_create_a_new_user { User.last(:conditions => {:login => 'register'}) }
205 should_create_a_new_user { User.last(:conditions => {:login => 'register'}) }
199
206
200 should 'set the user status to active' do
207 should 'set the user status to active' do
201 user = User.last(:conditions => {:login => 'register'})
208 user = User.last(:conditions => {:login => 'register'})
202 assert user
209 assert user
203 assert_equal User::STATUS_ACTIVE, user.status
210 assert_equal User::STATUS_ACTIVE, user.status
204 end
211 end
205 end
212 end
206
213
207 context "with self registration off" do
214 context "with self registration off" do
208 setup do
215 setup do
209 Setting.self_registration = '0'
216 Setting.self_registration = '0'
210 post :register
217 post :register
211 end
218 end
212
219
213 should_redirect_to('/') { home_url }
220 should_redirect_to('/') { home_url }
214 end
221 end
215 end
222 end
216
223
217 end
224 end
@@ -1,241 +1,241
1 require 'uri'
1 require 'uri'
2 require 'openid/extensions/sreg'
2 require 'openid/extensions/sreg'
3 require 'openid/extensions/ax'
3 require 'openid/extensions/ax'
4 require 'openid/store/filesystem'
4 require 'openid/store/filesystem'
5
5
6 require File.dirname(__FILE__) + '/open_id_authentication/db_store'
6 require File.dirname(__FILE__) + '/open_id_authentication/db_store'
7 require File.dirname(__FILE__) + '/open_id_authentication/mem_cache_store'
7 require File.dirname(__FILE__) + '/open_id_authentication/mem_cache_store'
8 require File.dirname(__FILE__) + '/open_id_authentication/request'
8 require File.dirname(__FILE__) + '/open_id_authentication/request'
9 require File.dirname(__FILE__) + '/open_id_authentication/timeout_fixes' if OpenID::VERSION == "2.0.4"
9 require File.dirname(__FILE__) + '/open_id_authentication/timeout_fixes' if OpenID::VERSION == "2.0.4"
10
10
11 module OpenIdAuthentication
11 module OpenIdAuthentication
12 OPEN_ID_AUTHENTICATION_DIR = RAILS_ROOT + "/tmp/openids"
12 OPEN_ID_AUTHENTICATION_DIR = RAILS_ROOT + "/tmp/openids"
13
13
14 def self.store
14 def self.store
15 @@store
15 @@store
16 end
16 end
17
17
18 def self.store=(*store_option)
18 def self.store=(*store_option)
19 store, *parameters = *([ store_option ].flatten)
19 store, *parameters = *([ store_option ].flatten)
20
20
21 @@store = case store
21 @@store = case store
22 when :db
22 when :db
23 OpenIdAuthentication::DbStore.new
23 OpenIdAuthentication::DbStore.new
24 when :mem_cache
24 when :mem_cache
25 OpenIdAuthentication::MemCacheStore.new(*parameters)
25 OpenIdAuthentication::MemCacheStore.new(*parameters)
26 when :file
26 when :file
27 OpenID::Store::Filesystem.new(OPEN_ID_AUTHENTICATION_DIR)
27 OpenID::Store::Filesystem.new(OPEN_ID_AUTHENTICATION_DIR)
28 else
28 else
29 raise "Unknown store: #{store}"
29 raise "Unknown store: #{store}"
30 end
30 end
31 end
31 end
32
32
33 self.store = :db
33 self.store = :db
34
34
35 class InvalidOpenId < StandardError
35 class InvalidOpenId < StandardError
36 end
36 end
37
37
38 class Result
38 class Result
39 ERROR_MESSAGES = {
39 ERROR_MESSAGES = {
40 :missing => "Sorry, the OpenID server couldn't be found",
40 :missing => "Sorry, the OpenID server couldn't be found",
41 :invalid => "Sorry, but this does not appear to be a valid OpenID",
41 :invalid => "Sorry, but this does not appear to be a valid OpenID",
42 :canceled => "OpenID verification was canceled",
42 :canceled => "OpenID verification was canceled",
43 :failed => "OpenID verification failed",
43 :failed => "OpenID verification failed",
44 :setup_needed => "OpenID verification needs setup"
44 :setup_needed => "OpenID verification needs setup"
45 }
45 }
46
46
47 def self.[](code)
47 def self.[](code)
48 new(code)
48 new(code)
49 end
49 end
50
50
51 def initialize(code)
51 def initialize(code)
52 @code = code
52 @code = code
53 end
53 end
54
54
55 def status
55 def status
56 @code
56 @code
57 end
57 end
58
58
59 ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
59 ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
60
60
61 def successful?
61 def successful?
62 @code == :successful
62 @code == :successful
63 end
63 end
64
64
65 def unsuccessful?
65 def unsuccessful?
66 ERROR_MESSAGES.keys.include?(@code)
66 ERROR_MESSAGES.keys.include?(@code)
67 end
67 end
68
68
69 def message
69 def message
70 ERROR_MESSAGES[@code]
70 ERROR_MESSAGES[@code]
71 end
71 end
72 end
72 end
73
73
74 # normalizes an OpenID according to http://openid.net/specs/openid-authentication-2_0.html#normalization
74 # normalizes an OpenID according to http://openid.net/specs/openid-authentication-2_0.html#normalization
75 def self.normalize_identifier(identifier)
75 def self.normalize_identifier(identifier)
76 # clean up whitespace
76 # clean up whitespace
77 identifier = identifier.to_s.strip
77 identifier = identifier.to_s.strip
78
78
79 # if an XRI has a prefix, strip it.
79 # if an XRI has a prefix, strip it.
80 identifier.gsub!(/xri:\/\//i, '')
80 identifier.gsub!(/xri:\/\//i, '')
81
81
82 # dodge XRIs -- TODO: validate, don't just skip.
82 # dodge XRIs -- TODO: validate, don't just skip.
83 unless ['=', '@', '+', '$', '!', '('].include?(identifier.at(0))
83 unless ['=', '@', '+', '$', '!', '('].include?(identifier.at(0))
84 # does it begin with http? if not, add it.
84 # does it begin with http? if not, add it.
85 identifier = "http://#{identifier}" unless identifier =~ /^http/i
85 identifier = "http://#{identifier}" unless identifier =~ /^http/i
86
86
87 # strip any fragments
87 # strip any fragments
88 identifier.gsub!(/\#(.*)$/, '')
88 identifier.gsub!(/\#(.*)$/, '')
89
89
90 begin
90 begin
91 uri = URI.parse(identifier)
91 uri = URI.parse(identifier)
92 uri.scheme = uri.scheme.downcase # URI should do this
92 uri.scheme = uri.scheme.downcase if uri.scheme # URI should do this
93 identifier = uri.normalize.to_s
93 identifier = uri.normalize.to_s
94 rescue URI::InvalidURIError
94 rescue URI::InvalidURIError
95 raise InvalidOpenId.new("#{identifier} is not an OpenID identifier")
95 raise InvalidOpenId.new("#{identifier} is not an OpenID identifier")
96 end
96 end
97 end
97 end
98
98
99 return identifier
99 return identifier
100 end
100 end
101
101
102 # deprecated for OpenID 2.0, where not all OpenIDs are URLs
102 # deprecated for OpenID 2.0, where not all OpenIDs are URLs
103 def self.normalize_url(url)
103 def self.normalize_url(url)
104 ActiveSupport::Deprecation.warn "normalize_url has been deprecated, use normalize_identifier instead"
104 ActiveSupport::Deprecation.warn "normalize_url has been deprecated, use normalize_identifier instead"
105 self.normalize_identifier(url)
105 self.normalize_identifier(url)
106 end
106 end
107
107
108 protected
108 protected
109 def normalize_url(url)
109 def normalize_url(url)
110 OpenIdAuthentication.normalize_url(url)
110 OpenIdAuthentication.normalize_url(url)
111 end
111 end
112
112
113 def normalize_identifier(url)
113 def normalize_identifier(url)
114 OpenIdAuthentication.normalize_identifier(url)
114 OpenIdAuthentication.normalize_identifier(url)
115 end
115 end
116
116
117 # The parameter name of "openid_identifier" is used rather than the Rails convention "open_id_identifier"
117 # The parameter name of "openid_identifier" is used rather than the Rails convention "open_id_identifier"
118 # because that's what the specification dictates in order to get browser auto-complete working across sites
118 # because that's what the specification dictates in order to get browser auto-complete working across sites
119 def using_open_id?(identity_url = nil) #:doc:
119 def using_open_id?(identity_url = nil) #:doc:
120 identity_url ||= params[:openid_identifier] || params[:openid_url]
120 identity_url ||= params[:openid_identifier] || params[:openid_url]
121 !identity_url.blank? || params[:open_id_complete]
121 !identity_url.blank? || params[:open_id_complete]
122 end
122 end
123
123
124 def authenticate_with_open_id(identity_url = nil, options = {}, &block) #:doc:
124 def authenticate_with_open_id(identity_url = nil, options = {}, &block) #:doc:
125 identity_url ||= params[:openid_identifier] || params[:openid_url]
125 identity_url ||= params[:openid_identifier] || params[:openid_url]
126
126
127 if params[:open_id_complete].nil?
127 if params[:open_id_complete].nil?
128 begin_open_id_authentication(identity_url, options, &block)
128 begin_open_id_authentication(identity_url, options, &block)
129 else
129 else
130 complete_open_id_authentication(&block)
130 complete_open_id_authentication(&block)
131 end
131 end
132 end
132 end
133
133
134 private
134 private
135 def begin_open_id_authentication(identity_url, options = {})
135 def begin_open_id_authentication(identity_url, options = {})
136 identity_url = normalize_identifier(identity_url)
136 identity_url = normalize_identifier(identity_url)
137 return_to = options.delete(:return_to)
137 return_to = options.delete(:return_to)
138 method = options.delete(:method)
138 method = options.delete(:method)
139
139
140 options[:required] ||= [] # reduces validation later
140 options[:required] ||= [] # reduces validation later
141 options[:optional] ||= []
141 options[:optional] ||= []
142
142
143 open_id_request = open_id_consumer.begin(identity_url)
143 open_id_request = open_id_consumer.begin(identity_url)
144 add_simple_registration_fields(open_id_request, options)
144 add_simple_registration_fields(open_id_request, options)
145 add_ax_fields(open_id_request, options)
145 add_ax_fields(open_id_request, options)
146 redirect_to(open_id_redirect_url(open_id_request, return_to, method))
146 redirect_to(open_id_redirect_url(open_id_request, return_to, method))
147 rescue OpenIdAuthentication::InvalidOpenId => e
147 rescue OpenIdAuthentication::InvalidOpenId => e
148 yield Result[:invalid], identity_url, nil
148 yield Result[:invalid], identity_url, nil
149 rescue OpenID::OpenIDError, Timeout::Error => e
149 rescue OpenID::OpenIDError, Timeout::Error => e
150 logger.error("[OPENID] #{e}")
150 logger.error("[OPENID] #{e}")
151 yield Result[:missing], identity_url, nil
151 yield Result[:missing], identity_url, nil
152 end
152 end
153
153
154 def complete_open_id_authentication
154 def complete_open_id_authentication
155 params_with_path = params.reject { |key, value| request.path_parameters[key] }
155 params_with_path = params.reject { |key, value| request.path_parameters[key] }
156 params_with_path.delete(:format)
156 params_with_path.delete(:format)
157 open_id_response = timeout_protection_from_identity_server { open_id_consumer.complete(params_with_path, requested_url) }
157 open_id_response = timeout_protection_from_identity_server { open_id_consumer.complete(params_with_path, requested_url) }
158 identity_url = normalize_identifier(open_id_response.display_identifier) if open_id_response.display_identifier
158 identity_url = normalize_identifier(open_id_response.display_identifier) if open_id_response.display_identifier
159
159
160 case open_id_response.status
160 case open_id_response.status
161 when OpenID::Consumer::SUCCESS
161 when OpenID::Consumer::SUCCESS
162 profile_data = {}
162 profile_data = {}
163
163
164 # merge the SReg data and the AX data into a single hash of profile data
164 # merge the SReg data and the AX data into a single hash of profile data
165 [ OpenID::SReg::Response, OpenID::AX::FetchResponse ].each do |data_response|
165 [ OpenID::SReg::Response, OpenID::AX::FetchResponse ].each do |data_response|
166 if data_response.from_success_response( open_id_response )
166 if data_response.from_success_response( open_id_response )
167 profile_data.merge! data_response.from_success_response( open_id_response ).data
167 profile_data.merge! data_response.from_success_response( open_id_response ).data
168 end
168 end
169 end
169 end
170
170
171 yield Result[:successful], identity_url, profile_data
171 yield Result[:successful], identity_url, profile_data
172 when OpenID::Consumer::CANCEL
172 when OpenID::Consumer::CANCEL
173 yield Result[:canceled], identity_url, nil
173 yield Result[:canceled], identity_url, nil
174 when OpenID::Consumer::FAILURE
174 when OpenID::Consumer::FAILURE
175 yield Result[:failed], identity_url, nil
175 yield Result[:failed], identity_url, nil
176 when OpenID::Consumer::SETUP_NEEDED
176 when OpenID::Consumer::SETUP_NEEDED
177 yield Result[:setup_needed], open_id_response.setup_url, nil
177 yield Result[:setup_needed], open_id_response.setup_url, nil
178 end
178 end
179 end
179 end
180
180
181 def open_id_consumer
181 def open_id_consumer
182 OpenID::Consumer.new(session, OpenIdAuthentication.store)
182 OpenID::Consumer.new(session, OpenIdAuthentication.store)
183 end
183 end
184
184
185 def add_simple_registration_fields(open_id_request, fields)
185 def add_simple_registration_fields(open_id_request, fields)
186 sreg_request = OpenID::SReg::Request.new
186 sreg_request = OpenID::SReg::Request.new
187
187
188 # filter out AX identifiers (URIs)
188 # filter out AX identifiers (URIs)
189 required_fields = fields[:required].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
189 required_fields = fields[:required].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
190 optional_fields = fields[:optional].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
190 optional_fields = fields[:optional].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
191
191
192 sreg_request.request_fields(required_fields, true) unless required_fields.blank?
192 sreg_request.request_fields(required_fields, true) unless required_fields.blank?
193 sreg_request.request_fields(optional_fields, false) unless optional_fields.blank?
193 sreg_request.request_fields(optional_fields, false) unless optional_fields.blank?
194 sreg_request.policy_url = fields[:policy_url] if fields[:policy_url]
194 sreg_request.policy_url = fields[:policy_url] if fields[:policy_url]
195 open_id_request.add_extension(sreg_request)
195 open_id_request.add_extension(sreg_request)
196 end
196 end
197
197
198 def add_ax_fields( open_id_request, fields )
198 def add_ax_fields( open_id_request, fields )
199 ax_request = OpenID::AX::FetchRequest.new
199 ax_request = OpenID::AX::FetchRequest.new
200
200
201 # look through the :required and :optional fields for URIs (AX identifiers)
201 # look through the :required and :optional fields for URIs (AX identifiers)
202 fields[:required].each do |f|
202 fields[:required].each do |f|
203 next unless f =~ /^https?:\/\//
203 next unless f =~ /^https?:\/\//
204 ax_request.add( OpenID::AX::AttrInfo.new( f, nil, true ) )
204 ax_request.add( OpenID::AX::AttrInfo.new( f, nil, true ) )
205 end
205 end
206
206
207 fields[:optional].each do |f|
207 fields[:optional].each do |f|
208 next unless f =~ /^https?:\/\//
208 next unless f =~ /^https?:\/\//
209 ax_request.add( OpenID::AX::AttrInfo.new( f, nil, false ) )
209 ax_request.add( OpenID::AX::AttrInfo.new( f, nil, false ) )
210 end
210 end
211
211
212 open_id_request.add_extension( ax_request )
212 open_id_request.add_extension( ax_request )
213 end
213 end
214
214
215 def open_id_redirect_url(open_id_request, return_to = nil, method = nil)
215 def open_id_redirect_url(open_id_request, return_to = nil, method = nil)
216 open_id_request.return_to_args['_method'] = (method || request.method).to_s
216 open_id_request.return_to_args['_method'] = (method || request.method).to_s
217 open_id_request.return_to_args['open_id_complete'] = '1'
217 open_id_request.return_to_args['open_id_complete'] = '1'
218 open_id_request.redirect_url(root_url, return_to || requested_url)
218 open_id_request.redirect_url(root_url, return_to || requested_url)
219 end
219 end
220
220
221 def requested_url
221 def requested_url
222 relative_url_root = self.class.respond_to?(:relative_url_root) ?
222 relative_url_root = self.class.respond_to?(:relative_url_root) ?
223 self.class.relative_url_root.to_s :
223 self.class.relative_url_root.to_s :
224 request.relative_url_root
224 request.relative_url_root
225 "#{request.protocol}#{request.host_with_port}#{relative_url_root}#{request.path}"
225 "#{request.protocol}#{request.host_with_port}#{relative_url_root}#{request.path}"
226 end
226 end
227
227
228 def timeout_protection_from_identity_server
228 def timeout_protection_from_identity_server
229 yield
229 yield
230 rescue Timeout::Error
230 rescue Timeout::Error
231 Class.new do
231 Class.new do
232 def status
232 def status
233 OpenID::FAILURE
233 OpenID::FAILURE
234 end
234 end
235
235
236 def msg
236 def msg
237 "Identity server timed out"
237 "Identity server timed out"
238 end
238 end
239 end.new
239 end.new
240 end
240 end
241 end
241 end
General Comments 0
You need to be logged in to leave comments. Login now