У меня также были проблемы с генерацией подходящей подписи, и, наконец, я нашел решение.
Как вы уже подозревали, вы должны добавить значения из пространства имен openid.ax
, применяя то же правило добавления пары ключ / значение без префикса openid.
. Если нет ключей openid.ax
, значит что-то не так.
Да, за последней парой ключ / значение следует новая строка (внимание: только \n
). Это могло бы быть более четко упомянуто в спецификации OpenID.
Вы ошибаетесь в кодировке URL, все наоборот: значения должны быть декодированными URL . Также это явно не указано в спецификации. Не путайте двоеточия и точки с запятой, вам не разрешено иметь двоеточия , но только в ключевой части, поэтому проблем с этим нет.
Так что, если вы попробуете с этой строкой и добавите отсутствующие пары ключ / значение, она должна работать:
ns:http://specs.openid.net/auth/2.0
op_endpoint:https://www.google.com/accounts/o8/ud
claimed_id:https://www.google.com/accounts/o8/id?id=AItOawlvj7acGYj-NH1kKKl3RswJlLCKpl9LIwk
identity:https://www.google.com/accounts/o8/id?id=AItOawlvj7acGYj-NH1kKKl3RswJlLCKpl9LIwk
return_to:http://mysite.com/Account/Login.aspx
response_nonce:2011-05-12T03:56:09ZoeDC9WFOgOBaAQ
assoc_handle:AOQobUdHugprvbsK2-8NCtS2uBomRDGJQGOKDmqEwxco8Rny47rdZlBp
ns.ext1:http://openid.net/srv/ax/1.0
ext1.mode:fetch_response
ext1.type.firstname:http://axschema.org/namePerson/first
ext1.value.firstname:First
ext1.type.email:http://schema.openid.net/contact/email
ext1.value.email:myemail@gmail.com
ext1.type.lastname:http://axschema.org/namePerson/last
ext1.value.lastname:Name
Это маленькое консольное приложение повторно генерирует подпись (используя HMAC-SHA256), для этого нужны два параметра:
- полный URL-адрес перенаправления после успешной аутентификации OpenID (содержащий положительные ключи подтверждения), можно скопировать из адресной строки веб-браузера
- ключ MAC в кодировке Base64, как возвращено в предыдущем ответе на ассоциацию
Код:
using System;
public class OpenIdSignatureVerification {
public static void Main(string[] args) {
if (args.Length != 2) {
Console.Error.WriteLine("Usage: assertion_url mac_key");
Environment.Exit(1);
}
string url = args[0];
int pos = url.IndexOf('?');
if (pos == -1) {
Console.Error.WriteLine("No query string found");
Environment.Exit(1);
}
url = url.Substring(pos + 1);
Console.WriteLine(String.Format("Query string: {0}", url));
System.Collections.Generic.Dictionary<string, string> dict = new System.Collections.Generic.Dictionary<string, string>();
foreach (string part in url.Split('&')) {
string[] keyValue = part.Split('=');
if (keyValue.Length != 2) continue;
dict[keyValue[0]] = System.Web.HttpUtility.UrlDecode(keyValue[1]);
}
string hashInput = String.Empty;
string[] signed = dict["openid.signed"].Replace("%2C", ",").Split(',');
foreach (string key in signed) hashInput += key + ":" + dict["openid." + key] + "\n";
string macKey = args[1];
Console.WriteLine(String.Format("Hash input: {0}\n", hashInput));
Console.WriteLine(String.Format("MAC Key: {0}", macKey));
byte[] encodedHashInput = System.Text.Encoding.UTF8.GetBytes(hashInput);
System.Security.Cryptography.HMACSHA256 signer = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(macKey));
string hashOutput = Convert.ToBase64String(signer.ComputeHash(encodedHashInput));
Console.WriteLine(String.Format("Signature hash (expected) : {0}", dict["openid.sig"]));
Console.WriteLine(String.Format("Signature hash (calculated): {0}", hashOutput));
}
}