OLD | NEW |
(Empty) | |
| 1 <?php |
| 2 /** |
| 3 * This class provides a simple interface for OpenID (1.1 and 2.0) authenticatio
n. |
| 4 * Supports Yadis discovery. |
| 5 * The authentication process is stateless/dumb. |
| 6 * |
| 7 * Usage: |
| 8 * Sign-on with OpenID is a two step process: |
| 9 * Step one is authentication with the provider: |
| 10 * <code> |
| 11 * $openid = new LightOpenID; |
| 12 * $openid->identity = 'ID supplied by user'; |
| 13 * header('Location: ' . $openid->authUrl()); |
| 14 * </code> |
| 15 * The provider then sends various parameters via GET, one of them is openid_mod
e. |
| 16 * Step two is verification: |
| 17 * <code> |
| 18 * if ($this->data['openid_mode']) { |
| 19 * $openid = new LightOpenID; |
| 20 * echo $openid->validate() ? 'Logged in.' : 'Failed'; |
| 21 * } |
| 22 * </code> |
| 23 * |
| 24 * Optionally, you can set $returnUrl and $realm (or $trustRoot, which is an ali
as). |
| 25 * The default values for those are: |
| 26 * $openid->realm = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' .
$_SERVER['HTTP_HOST']; |
| 27 * $openid->returnUrl = $openid->realm . $_SERVER['REQUEST_URI']; |
| 28 * If you don't know their meaning, refer to any openid tutorial, or specificati
on. Or just guess. |
| 29 * |
| 30 * AX and SREG extensions are supported. |
| 31 * To use them, specify $openid->required and/or $openid->optional. |
| 32 * These are arrays, with values being AX schema paths (the 'path' part of the U
RL). |
| 33 * For example: |
| 34 * $openid->required = array('namePerson/friendly', 'contact/email'); |
| 35 * $openid->optional = array('namePerson/first'); |
| 36 * If the server supports only SREG or OpenID 1.1, these are automaticaly |
| 37 * mapped to SREG names, so that user doesn't have to know anything about the se
rver. |
| 38 * |
| 39 * To get the values, use $openid->getAttributes(). |
| 40 * |
| 41 * |
| 42 * The library depends on curl, and requires PHP 5. |
| 43 * @author Mewp |
| 44 * @copyright Copyright (c) 2010, Mewp |
| 45 * @license http://www.opensource.org/licenses/mit-license.php MIT |
| 46 */ |
| 47 class LightOpenID |
| 48 { |
| 49 public $returnUrl |
| 50 , $required = array() |
| 51 , $optional = array(); |
| 52 private $identity, $claimed_id; |
| 53 protected $server, $version, $trustRoot, $aliases, $identifier_select = fals
e |
| 54 , $ax = false, $sreg = false, $data; |
| 55 static protected $ax_to_sreg = array( |
| 56 'namePerson/friendly' => 'nickname', |
| 57 'contact/email' => 'email', |
| 58 'namePerson' => 'fullname', |
| 59 'birthDate' => 'dob', |
| 60 'person/gender' => 'gender', |
| 61 'contact/postalCode/home' => 'postcode', |
| 62 'contact/country/home' => 'country', |
| 63 'pref/language' => 'language', |
| 64 'pref/timezone' => 'timezone', |
| 65 ); |
| 66 |
| 67 function __construct() |
| 68 { |
| 69 $this->trustRoot = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://
' . $_SERVER['HTTP_HOST']; |
| 70 $this->returnUrl = $this->trustRoot . $_SERVER['REQUEST_URI']; |
| 71 |
| 72 if (!function_exists('curl_exec')) { |
| 73 throw new ErrorException('Curl extension is required.'); |
| 74 } |
| 75 |
| 76 $this->data = $_POST + $_GET; # OPs may send data as POST or GET. |
| 77 } |
| 78 |
| 79 function __set($name, $value) |
| 80 { |
| 81 switch ($name) { |
| 82 case 'identity': |
| 83 if (strlen($value = trim($value))) { |
| 84 if (preg_match('#^xri:/*#i', $value, $m)) { |
| 85 $value = substr($value, strlen($m[0])); |
| 86 } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) { |
| 87 $value = "http://$value"; |
| 88 } |
| 89 if (preg_match('#^https?://[^/]+$#i', $value, $m)) { |
| 90 $value .= '/'; |
| 91 } |
| 92 } |
| 93 $this->$name = $this->claimed_id = $value; |
| 94 break; |
| 95 case 'trustRoot': |
| 96 case 'realm': |
| 97 $this->trustRoot = trim($value); |
| 98 } |
| 99 } |
| 100 |
| 101 function __get($name) |
| 102 { |
| 103 switch ($name) { |
| 104 case 'identity': |
| 105 # We return claimed_id instead of identity, |
| 106 # because the developer should see the claimed identifier, |
| 107 # i.e. what he set as identity, not the op-local identifier (which i
s what we verify) |
| 108 return $this->claimed_id; |
| 109 case 'trustRoot': |
| 110 case 'realm': |
| 111 return $this->trustRoot; |
| 112 } |
| 113 } |
| 114 |
| 115 protected function request($url, $method='GET', $params=array()) |
| 116 { |
| 117 $params = http_build_query($params, '', '&'); |
| 118 $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params :
'')); |
| 119 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); |
| 120 curl_setopt($curl, CURLOPT_HEADER, false); |
| 121 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); |
| 122 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
| 123 if ($method == 'POST') { |
| 124 curl_setopt($curl, CURLOPT_POST, true); |
| 125 curl_setopt($curl, CURLOPT_POSTFIELDS, $params); |
| 126 } elseif ($method == 'HEAD') { |
| 127 curl_setopt($curl, CURLOPT_HEADER, true); |
| 128 curl_setopt($curl, CURLOPT_NOBODY, true); |
| 129 } else { |
| 130 curl_setopt($curl, CURLOPT_HTTPGET, true); |
| 131 } |
| 132 $response = curl_exec($curl); |
| 133 |
| 134 if (curl_errno($curl)) { |
| 135 throw new ErrorException(curl_error($curl), curl_errno($curl)); |
| 136 } |
| 137 |
| 138 return $response; |
| 139 } |
| 140 |
| 141 protected function build_url($url, $parts) |
| 142 { |
| 143 if (isset($url['query'], $parts['query'])) { |
| 144 $parts['query'] = $url['query'] . '&' . $parts['query']; |
| 145 } |
| 146 |
| 147 $url = $parts + $url; |
| 148 $url = $url['scheme'] . '://' |
| 149 . (empty($url['username'])?'' |
| 150 :(empty($url['password'])? "{$url['username']}@" |
| 151 :"{$url['username']}:{$url['password']}@")) |
| 152 . $url['host'] |
| 153 . (empty($url['port'])?'':":{$url['port']}") |
| 154 . (empty($url['path'])?'':$url['path']) |
| 155 . (empty($url['query'])?'':"?{$url['query']}") |
| 156 . (empty($url['fragment'])?'':":{$url['fragment']}"); |
| 157 return $url; |
| 158 } |
| 159 |
| 160 /** |
| 161 * Helper function used to scan for <meta>/<link> tags and extract informati
on |
| 162 * from them |
| 163 */ |
| 164 protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName
) |
| 165 { |
| 166 preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$v
alueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1); |
| 167 preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['
\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2); |
| 168 |
| 169 $result = array_merge($matches1[1], $matches2[1]); |
| 170 return empty($result)?false:$result[0]; |
| 171 } |
| 172 |
| 173 /** |
| 174 * Performs Yadis and HTML discovery. Normally not used. |
| 175 * @param $url Identity URL. |
| 176 * @return String OP Endpoint (i.e. OpenID provider address). |
| 177 * @throws ErrorException |
| 178 */ |
| 179 function discover($url) |
| 180 { |
| 181 if (!$url) throw new ErrorException('No identity supplied.'); |
| 182 # Use xri.net proxy to resolve i-name identities |
| 183 if (!preg_match('#^https?:#', $url)) { |
| 184 $url = "https://xri.net/$url"; |
| 185 } |
| 186 |
| 187 # We save the original url in case of Yadis discovery failure. |
| 188 # It can happen when we'll be lead to an XRDS document |
| 189 # which does not have any OpenID2 services. |
| 190 $originalUrl = $url; |
| 191 |
| 192 # A flag to disable yadis discovery in case of failure in headers. |
| 193 $yadis = true; |
| 194 |
| 195 # We'll jump a maximum of 5 times, to avoid endless redirections. |
| 196 for ($i = 0; $i < 5; $i ++) { |
| 197 if ($yadis) { |
| 198 $headers = explode("\n",$this->request($url, 'HEAD')); |
| 199 |
| 200 $next = false; |
| 201 foreach ($headers as $header) { |
| 202 if (preg_match('#X-XRDS-Location\s*:\s*(.*)#', $header, $m))
{ |
| 203 $url = $this->build_url(parse_url($url), parse_url(trim(
$m[1]))); |
| 204 $next = true; |
| 205 } |
| 206 |
| 207 if (preg_match('#Content-Type\s*:\s*application/xrds\+xml#i'
, $header)) { |
| 208 # Found an XRDS document, now let's find the server, and
optionally delegate. |
| 209 $content = $this->request($url, 'GET'); |
| 210 |
| 211 # OpenID 2 |
| 212 # We ignore it for MyOpenID, as it breaks sreg if using
OpenID 2.0 |
| 213 $ns = preg_quote('http://specs.openid.net/auth/2.0/'); |
| 214 if (preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'(.*?)\s
*</Type>(.*)</Service>#s', $content, $m)) { |
| 215 $content = ' ' . $m[1] . $m[3]; # The space is added
, so that strpos doesn't return 0. |
| 216 if ($m[2] == 'server') $this->identifier_select = tr
ue; |
| 217 |
| 218 preg_match('#<URI.*?>(.*)</URI>#', $content, $server
); |
| 219 preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $co
ntent, $delegate); |
| 220 if (empty($server)) { |
| 221 return false; |
| 222 } |
| 223 # Does the server advertise support for either AX or
SREG? |
| 224 $this->ax = (bool) strpos($content, '<Type>http://
openid.net/srv/ax/1.0</Type>'); |
| 225 $this->sreg = strpos($content, '<Type>http://openid.
net/sreg/1.0</Type>') |
| 226 || strpos($content, '<Type>http://openid.
net/extensions/sreg/1.1</Type>'); |
| 227 |
| 228 $server = $server[1]; |
| 229 if (isset($delegate[2])) $this->identity = trim($del
egate[2]); |
| 230 $this->version = 2; |
| 231 |
| 232 $this->server = $server; |
| 233 return $server; |
| 234 } |
| 235 |
| 236 # OpenID 1.1 |
| 237 $ns = preg_quote('http://openid.net/signon/1.1'); |
| 238 if (preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'\s*</Ty
pe>(.*)</Service>#s', $content, $m)) { |
| 239 $content = ' ' . $m[1] . $m[2]; |
| 240 |
| 241 preg_match('#<URI.*?>(.*)</URI>#', $content, $server
); |
| 242 preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $con
tent, $delegate); |
| 243 if (empty($server)) { |
| 244 return false; |
| 245 } |
| 246 # AX can be used only with OpenID 2.0, so checking o
nly SREG |
| 247 $this->sreg = strpos($content, '<Type>http://openid.
net/sreg/1.0</Type>') |
| 248 || strpos($content, '<Type>http://openid.
net/extensions/sreg/1.1</Type>'); |
| 249 |
| 250 $server = $server[1]; |
| 251 if (isset($delegate[1])) $this->identity = $delegate
[1]; |
| 252 $this->version = 1; |
| 253 |
| 254 $this->server = $server; |
| 255 return $server; |
| 256 } |
| 257 |
| 258 $next = true; |
| 259 $yadis = false; |
| 260 $url = $originalUrl; |
| 261 $content = null; |
| 262 break; |
| 263 } |
| 264 } |
| 265 if ($next) continue; |
| 266 |
| 267 # There are no relevant information in headers, so we search the
body. |
| 268 $content = $this->request($url, 'GET'); |
| 269 if ($location = $this->htmlTag($content, 'meta', 'http-equiv', '
X-XRDS-Location', 'value')) { |
| 270 $url = $this->build_url(parse_url($url), parse_url($location
)); |
| 271 continue; |
| 272 } |
| 273 } |
| 274 |
| 275 if (!$content) $content = $this->request($url, 'GET'); |
| 276 |
| 277 # At this point, the YADIS Discovery has failed, so we'll switch |
| 278 # to openid2 HTML discovery, then fallback to openid 1.1 discovery. |
| 279 $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provide
r', 'href'); |
| 280 $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_i
d', 'href'); |
| 281 $this->version = 2; |
| 282 |
| 283 if (!$server) { |
| 284 # The same with openid 1.1 |
| 285 $server = $this->htmlTag($content, 'link', 'rel', 'openid.serv
er', 'href'); |
| 286 $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.dele
gate', 'href'); |
| 287 $this->version = 1; |
| 288 } |
| 289 |
| 290 if ($server) { |
| 291 # We found an OpenID2 OP Endpoint |
| 292 if ($delegate) { |
| 293 # We have also found an OP-Local ID. |
| 294 $this->identity = $delegate; |
| 295 } |
| 296 $this->server = $server; |
| 297 return $server; |
| 298 } |
| 299 |
| 300 throw new ErrorException('No servers found!'); |
| 301 } |
| 302 throw new ErrorException('Endless redirection!'); |
| 303 } |
| 304 |
| 305 protected function sregParams() |
| 306 { |
| 307 $params = array(); |
| 308 # We always use SREG 1.1, even if the server is advertising only support
for 1.0. |
| 309 # That's because it's fully backwards compatibile with 1.0, and some pro
viders |
| 310 # advertise 1.0 even if they accept only 1.1. One such provider is myope
nid.com |
| 311 $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1'; |
| 312 if ($this->required) { |
| 313 $params['openid.sreg.required'] = array(); |
| 314 foreach ($this->required as $required) { |
| 315 if (!isset(self::$ax_to_sreg[$required])) continue; |
| 316 $params['openid.sreg.required'][] = self::$ax_to_sreg[$required]
; |
| 317 } |
| 318 $params['openid.sreg.required'] = implode(',', $params['openid.sreg.
required']); |
| 319 } |
| 320 |
| 321 if ($this->optional) { |
| 322 $params['openid.sreg.optional'] = array(); |
| 323 foreach ($this->optional as $optional) { |
| 324 if (!isset(self::$ax_to_sreg[$optional])) continue; |
| 325 $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional]
; |
| 326 } |
| 327 $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.
optional']); |
| 328 } |
| 329 return $params; |
| 330 } |
| 331 protected function axParams() |
| 332 { |
| 333 $params = array(); |
| 334 if ($this->required || $this->optional) { |
| 335 $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0'; |
| 336 $params['openid.ax.mode'] = 'fetch_request'; |
| 337 $this->aliases = array(); |
| 338 $counts = array(); |
| 339 $required = array(); |
| 340 $optional = array(); |
| 341 foreach (array('required','optional') as $type) { |
| 342 foreach ($this->$type as $alias => $field) { |
| 343 if (is_int($alias)) $alias = strtr($field, '/', '_'); |
| 344 $this->aliases[$alias] = 'http://axschema.org/' . $field; |
| 345 if (empty($counts[$alias])) $counts[$alias] = 0; |
| 346 $counts[$alias] += 1; |
| 347 ${$type}[] = $alias; |
| 348 } |
| 349 } |
| 350 foreach ($this->aliases as $alias => $ns) { |
| 351 $params['openid.ax.type.' . $alias] = $ns; |
| 352 } |
| 353 foreach ($counts as $alias => $count) { |
| 354 if ($count == 1) continue; |
| 355 $params['openid.ax.count.' . $alias] = $count; |
| 356 } |
| 357 |
| 358 # Don't send empty ax.requied and ax.if_available. |
| 359 # Google and possibly other providers refuse to support ax when one
of these is empty. |
| 360 if($required) { |
| 361 $params['openid.ax.required'] = implode(',', $required); |
| 362 } |
| 363 if($optional) { |
| 364 $params['openid.ax.if_available'] = implode(',', $optional); |
| 365 } |
| 366 } |
| 367 return $params; |
| 368 } |
| 369 |
| 370 protected function authUrl_v1() |
| 371 { |
| 372 $returnUrl = $this->returnUrl; |
| 373 # If we have an openid.delegate that is different from our claimed id, |
| 374 # we need to somehow preserve the claimed id between requests. |
| 375 # The simplest way is to just send it along with the return_to url. |
| 376 if($this->identity != $this->claimed_id) { |
| 377 $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claime
d_id=' . $this->claimed_id; |
| 378 } |
| 379 |
| 380 $params = array( |
| 381 'openid.return_to' => $returnUrl, |
| 382 'openid.mode' => 'checkid_setup', |
| 383 'openid.identity' => $this->identity, |
| 384 'openid.trust_root' => $this->trustRoot, |
| 385 ) + $this->sregParams(); |
| 386 |
| 387 return $this->build_url(parse_url($this->server) |
| 388 , array('query' => http_build_query($params, '',
'&'))); |
| 389 } |
| 390 |
| 391 protected function authUrl_v2($identifier_select) |
| 392 { |
| 393 $params = array( |
| 394 'openid.ns' => 'http://specs.openid.net/auth/2.0', |
| 395 'openid.mode' => 'checkid_setup', |
| 396 'openid.return_to' => $this->returnUrl, |
| 397 'openid.realm' => $this->trustRoot, |
| 398 ); |
| 399 if ($this->ax) { |
| 400 $params += $this->axParams(); |
| 401 } |
| 402 if ($this->sreg) { |
| 403 $params += $this->sregParams(); |
| 404 } |
| 405 if (!$this->ax && !$this->sreg) { |
| 406 # If OP doesn't advertise either SREG, nor AX, let's send them both |
| 407 # in worst case we don't get anything in return. |
| 408 $params += $this->axParams() + $this->sregParams(); |
| 409 } |
| 410 |
| 411 if ($identifier_select) { |
| 412 $params['openid.identity'] = $params['openid.claimed_id'] |
| 413 = 'http://specs.openid.net/auth/2.0/identifier_select'; |
| 414 } else { |
| 415 $params['openid.identity'] = $this->identity; |
| 416 $params['openid.claimed_id'] = $this->claimed_id; |
| 417 } |
| 418 |
| 419 return $this->build_url(parse_url($this->server) |
| 420 , array('query' => http_build_query($params, '',
'&'))); |
| 421 } |
| 422 |
| 423 /** |
| 424 * Returns authentication url. Usually, you want to redirect your user to it
. |
| 425 * @return String The authentication url. |
| 426 * @param String $select_identifier Whether to request OP to select identity
for an user in OpenID 2. Does not affect OpenID 1. |
| 427 * @throws ErrorException |
| 428 */ |
| 429 function authUrl($identifier_select = null) |
| 430 { |
| 431 if (!$this->server) $this->discover($this->identity); |
| 432 |
| 433 if ($this->version == 2) { |
| 434 if ($identifier_select === null) { |
| 435 return $this->authUrl_v2($this->identifier_select); |
| 436 } |
| 437 return $this->authUrl_v2($identifier_select); |
| 438 } |
| 439 return $this->authUrl_v1(); |
| 440 } |
| 441 |
| 442 /** |
| 443 * Performs OpenID verification with the OP. |
| 444 * @return Bool Whether the verification was successful. |
| 445 * @throws ErrorException |
| 446 */ |
| 447 function validate() |
| 448 { |
| 449 $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data[
'openid_claimed_id']:$this->data['openid_identity']; |
| 450 $params = array( |
| 451 'openid.assoc_handle' => $this->data['openid_assoc_handle'], |
| 452 'openid.signed' => $this->data['openid_signed'], |
| 453 'openid.sig' => $this->data['openid_sig'], |
| 454 ); |
| 455 |
| 456 if (isset($this->data['openid_op_endpoint'])) { |
| 457 # We're dealing with an OpenID 2.0 server, so let's set an ns |
| 458 # Even though we should know location of the endpoint, |
| 459 # we still need to verify it by discovery, so $server is not set her
e |
| 460 $params['openid.ns'] = 'http://specs.openid.net/auth/2.0'; |
| 461 } |
| 462 $server = $this->discover($this->data['openid_identity']); |
| 463 |
| 464 foreach (explode(',', $this->data['openid_signed']) as $item) { |
| 465 # Checking whether magic_quotes_gpc is turned on, because |
| 466 # the function may fail if it is. For example, when fetching |
| 467 # AX namePerson, it might containg an apostrophe, which will be esca
ped. |
| 468 # In such case, validation would fail, since we'd send different dat
a than OP |
| 469 # wants to verify. stripslashes() should solve that problem, but we
can't |
| 470 # use it when magic_quotes is off. |
| 471 $value = $this->data['openid_' . str_replace('.','_',$item)]; |
| 472 $params['openid.' . $item] = get_magic_quotes_gpc() ? stripslashes($
value) : $value; |
| 473 } |
| 474 |
| 475 $params['openid.mode'] = 'check_authentication'; |
| 476 |
| 477 $response = $this->request($server, 'POST', $params); |
| 478 |
| 479 return preg_match('/is_valid\s*:\s*true/i', $response); |
| 480 } |
| 481 protected function getAxAttributes() |
| 482 { |
| 483 $alias = null; |
| 484 if (isset($this->data['openid_ns_ax']) |
| 485 && $this->data['openid_ns_ax'] != 'http://openid.net/srv/ax/1.0' |
| 486 ) { # It's the most likely case, so we'll check it before |
| 487 $alias = 'ax'; |
| 488 } else { |
| 489 # 'ax' prefix is either undefined, or points to another extension, |
| 490 # so we search for another prefix |
| 491 foreach ($this->data as $key => $val) { |
| 492 if (substr($key, 0, strlen('openid_ns_')) == 'openid_ns_' |
| 493 && $val == 'http://openid.net/srv/ax/1.0' |
| 494 ) { |
| 495 $alias = substr($key, strlen('openid_ns_')); |
| 496 break; |
| 497 } |
| 498 } |
| 499 } |
| 500 if (!$alias) { |
| 501 # An alias for AX schema has not been found, |
| 502 # so there is no AX data in the OP's response |
| 503 return array(); |
| 504 } |
| 505 |
| 506 foreach ($this->data as $key => $value) { |
| 507 $keyMatch = 'openid_' . $alias . '_value_'; |
| 508 if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { |
| 509 continue; |
| 510 } |
| 511 $key = substr($key, strlen($keyMatch)); |
| 512 if (!isset($this->data['openid_' . $alias . '_type_' . $key])) { |
| 513 # OP is breaking the spec by returning a field without |
| 514 # associated ns. This shouldn't happen, but it's better |
| 515 # to check, than cause an E_NOTICE. |
| 516 continue; |
| 517 } |
| 518 $key = substr($this->data['openid_' . $alias . '_type_' . $key], |
| 519 strlen('http://axschema.org/')); |
| 520 $attributes[$key] = $value; |
| 521 } |
| 522 # Found the AX attributes, so no need to scan for SREG. |
| 523 return $attributes; |
| 524 } |
| 525 protected function getSregAttributes() |
| 526 { |
| 527 $attributes = array(); |
| 528 $sreg_to_ax = array_flip(self::$ax_to_sreg); |
| 529 foreach ($this->data as $key => $value) { |
| 530 $keyMatch = 'openid_sreg_'; |
| 531 if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { |
| 532 continue; |
| 533 } |
| 534 $key = substr($key, strlen($keyMatch)); |
| 535 if (!isset($sreg_to_ax[$key])) { |
| 536 # The field name isn't part of the SREG spec, so we ignore it. |
| 537 continue; |
| 538 } |
| 539 $attributes[$sreg_to_ax[$key]] = $value; |
| 540 } |
| 541 return $attributes; |
| 542 } |
| 543 /** |
| 544 * Gets AX/SREG attributes provided by OP. should be used only after success
ful validaton. |
| 545 * Note that it does not guarantee that any of the required/optional paramet
ers will be present, |
| 546 * or that there will be no other attributes besides those specified. |
| 547 * In other words. OP may provide whatever information it wants to. |
| 548 * * SREG names will be mapped to AX names. |
| 549 * * @return Array Array of attributes with keys being the AX schema nam
es, e.g. 'contact/email' |
| 550 * @see http://www.axschema.org/types/ |
| 551 */ |
| 552 function getAttributes() |
| 553 { |
| 554 $attributes; |
| 555 if (isset($this->data['openid_ns']) |
| 556 && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0' |
| 557 ) { # OpenID 2.0 |
| 558 # We search for both AX and SREG attributes, with AX taking preceden
ce. |
| 559 return $this->getAxAttributes() + $this->getSregAttributes(); |
| 560 } |
| 561 return $this->getSregAttributes(); |
| 562 } |
| 563 } |
OLD | NEW |