Index: modules/openid/openid.module =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/openid.module,v retrieving revision 1.19.2.11 diff -u -9 -p -r1.19.2.11 openid.module --- modules/openid/openid.module 11 Aug 2010 20:35:48 -0000 1.19.2.11 +++ modules/openid/openid.module 1 Dec 2010 22:47:45 -0000 @@ -528,49 +528,68 @@ function openid_authentication_request($ /** * Attempt to verify the response received from the OpenID Provider. * * @param $service * Array describing the OpenID provider. * @param $response * Array of response values from the provider. * * @return boolean + * @see http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4 */ function openid_verify_assertion($service, $response) { module_load_include('inc', 'openid'); // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.3 // Check the Nonce to protect against replay attacks. if (!openid_verify_assertion_nonce($service, $response)) { return FALSE; } // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4 // Verify the signatures. $valid = FALSE; - $association = db_fetch_object(db_query("SELECT * FROM {openid_association} WHERE assoc_handle = '%s'", $response['openid.assoc_handle'])); + $association = FALSE; + + // If the OP returned a openid.invalidate_handle, we have to proceed with + // direct verification: ignore the openid.assoc_handle, even if present. + // See http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4.1 + if (!empty($response['openid.assoc_handle']) && empty($response['openid.invalidate_handle'])) { + $association = db_fetch_object(db_query("SELECT * FROM {openid_association} WHERE assoc_handle = '%s'", $response['openid.assoc_handle'])); + } + if ($association && isset($association->session_type)) { // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4.2 // Verification using an association. $valid = openid_verify_assertion_signature($service, $association, $response); } else { // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4.3 // Direct verification. + // The verification requests contain all the fields from the response, + // except openid.mode. $request = $response; $request['openid.mode'] = 'check_authentication'; $message = _openid_create_message($request); $headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8'); $result = drupal_http_request($service['uri'], $headers, 'POST', _openid_encode_message($message)); if (!isset($result->error)) { $response = _openid_parse_message($result->data); + $response['invalidate_handle'] = '{HMAC-SHA1}{4cec4944}{N+vsHA==}'; + if (strtolower(trim($response['is_valid'])) == 'true') { $valid = TRUE; + if (!empty($response['invalidate_handle'])) { + // This association handle has expired on the OP side, remove it from the + // database to avoid reusing it again on a subsequent authentication request. + // See http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4.2.2 + db_query("DELETE FROM {openid_association} WHERE assoc_handle = '%s'", $response['invalidate_handle']); + } } else { $valid = FALSE; } } } return $valid; }