Class: OpenID::Consumer

Inherits:
Object
  • Object
show all
Includes:
OpenID
Defined in:
lib/openid/consumer.rb

Overview

class SimpleHTTPClient

Constant Summary

Constants included from OpenID

DEFAULT_DH_GEN, DEFAULT_DH_MODULUS, SECRET_SIZES

Instance Method Summary collapse

Methods included from OpenID

#append_args, #error_page, #from_btwoc, #normalize_url, #parse_kv, #parse_link_attrs, #quote_minimal, #redirect, #response_page, #sign_reply, #url_encode

Constructor Details

#initialize(http_client = SimpleHTTPClient.new(), association_manager = DumbAssociationManager.new()) ⇒ Consumer

Takes an http_client and an association_manager. Will create some automatically if none are passed in.



63
64
65
66
# File 'lib/openid/consumer.rb', line 63

def initialize(http_client = SimpleHTTPClient.new(), association_manager = DumbAssociationManager.new())
	@http_client = http_client
	@association_manager = association_manager
end

Instance Method Details

#_dumb_auth(server_url, now, req) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/openid/consumer.rb', line 140

def _dumb_auth(server_url, now, req)
	if !verify_return_to(req)
		raise ValueMismatchError, "return_to is not valid", caller
	end
	check_args = {}
	req.args.each { |k, v| check_args[k] = v if k.index('openid.') == 0 }
	check_args['openid.mode'] = 'check_authentication'
	body = url_encode(check_args)
	url, data = @http_client.post(server_url, body)
	results = parse_kv(data)
	lifetime = results['lifetime'].to_i
	if lifetime
		invalidate_handle = results['invalidate_handle']
		if invalidate_handle
			@association_manager.invalidate(server_url, invalidate_handle)
		end
		return now + lifetime
	else
		raise ValueMismatchError, 'Server failed to validate signature', caller
	end
end

#determine_server_url(req) ⇒ Object



110
111
112
113
114
115
116
# File 'lib/openid/consumer.rb', line 110

def determine_server_url(req)
	identity, server_url = find_server(req['identity'])
	if req['identity'] != identity
		raise ValueMismatchError, "ID URL #{req['identity']} seems to have moved: #{identity}", caller
	end
	return server_url
end

#do_cancel(req) ⇒ Object

Raises:



191
192
193
# File 'lib/openid/consumer.rb', line 191

def do_cancel(req)
	raise UserCancelled
end

#do_error(req) ⇒ Object

Handle an error from the server



182
183
184
185
186
187
188
189
# File 'lib/openid/consumer.rb', line 182

def do_error(req)
	error = req.get('error')
	if error
		raise ProtocolError, "Server Response: #{error}", caller
	else
		raise ProtocolError, "Unspecified Server Error: #{req.args}", caller
	end
end

#do_id_res(req) ⇒ Object

Raises:



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/openid/consumer.rb', line 162

def do_id_res(req)
	now = Time.now
	user_setup_url = req.get('user_setup_url')
	raise UserSetupNeeded, user_setup_url, caller if user_setup_url
	server_url = determine_server_url(req)
	assoc = @association_manager.get_association(server_url, req['assoc_handle'])
	if assoc == nil
		return _dumb_auth(server_url, now, req)
	end
	sig = req.get('sig')
	signed_fields = req.get('signed').strip.split(',')
	signed, v_sig = sign_reply(req.args, assoc.secret, signed_fields)
	if v_sig != sig
		raise ValueMismatchError, "Signatures did not match: #{req.args}, #{v_sig}, #{assoc.secret}", caller
	end
	issued = DateTime.strptime(req.get('issued')).to_time
	valid_to = [assoc.expiry, DateTime.strptime(req.get('valid_to')).to_time].min
	return now + (valid_to - issued)
end

#find_server(url) ⇒ Object

Returns identity_url, server_url or nil if no server is found.



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/openid/consumer.rb', line 119

def find_server(url)
	identity, data = @http_client.get(url)
	identity = identity.to_s
	server = nil
	delegate = nil
	parse_link_attrs(data) { |link|
		rel = link['rel']
		if rel == 'openid.server' and server == nil
			href = link['href']
			server = href if href
		end
		if rel == 'openid.delegate' and delegate == nil
			href = link['href']
			delegate = href if href
		end
	}
	return nil if !server
	identity = delegate if delegate
	return normalize_url(identity), normalize_url(server)
end

#handle_request(url, return_to, trust_root = nil, immediate = false) ⇒ Object

Returns the url to redirect to or nil if no identity is found



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/openid/consumer.rb', line 68

def handle_request(url, return_to, trust_root = nil, immediate = false)
	url = normalize_url(url)
	
	server_info = find_server(url)
	return nil if server_info == nil
	identity, server_url = server_info
	redir_args = { 'openid.identity' => identity, 'openid.return_to' => return_to}
	
	redir_args['openid.trust_root'] = trust_root if trust_root
	
	if immediate
		mode = 'checkid_immediate'
	else
		mode = 'checkid_setup'
	end
	
	redir_args['openid.mode'] = mode
	assoc_handle = @association_manager.associate(server_url)
	if assoc_handle
		redir_args['openid.assoc_handle'] = assoc_handle
	end
	
	return append_args(server_url, redir_args).to_s
end

#handle_response(req) ⇒ Object

Handles an OpenID GET request with openid.mode in the arguments. req should be a Request instance, properly initialized with the http arguments given, and the http method used to make the request. Returns the expiry time of the session as a Time.

Will raise a ProtocolError if the http_method is not GET, or the request mode is unknown.



99
100
101
102
103
104
105
106
107
108
# File 'lib/openid/consumer.rb', line 99

def handle_response(req)
	if req.http_method != 'GET'
		raise ProtocolError, "Expected HTTP Method 'GET', got #{req.http_method}", caller
	end
	begin
		return __send__('do_' + req['mode'], req)
	rescue NoMethodError
		raise ProtocolError, "Unknown Mode: #{req['mode']}", caller
	end
end

#verify_return_to(req) ⇒ Object

This is called before the consumer makes a check_authentication call to the server. It can be used to verify that the request being authenticated is valid by confirming that the openid.return_to value signed by the server corresponds to this consumer. The full OpenID::Request object is passed in. Should return true if the return_to field corresponds to this consumer, false otherwise. The default function performs no check and returns true.



201
202
203
# File 'lib/openid/consumer.rb', line 201

def verify_return_to(req)
	return true	
end