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