2014-12-29 5 views
2

Я прочитал учебник в https://developers.google.com/accounts/docs/OAuth2ServiceAccountFreebase oauth2 Bad Request (400) .Net

и попытался использовать их примеру, но получаю 400 плохой запрос. это мой код:

ClaimSet cs = new ClaimSet() 
     { 
      aud = "https://www.googleapis.com/oauth2/v3/token", 
      iss = "[email protected]eaccount.com", 
      exp = GetTime(DateTime.UtcNow.AddHours(1)).ToString(), 
      iat = GetTime(DateTime.UtcNow).ToString(), 
      scope = "https://www.googleapis.com/auth/freebase" 
     }; 

     //get the signed JWT 
     var signedJwt = JsonWebToken.Encode(cs);   


public static string Encode(object payload, JwtHashAlgorithm algorithm = JwtHashAlgorithm.RS256) 
     { 
      return Encode(payload, Encoding.UTF8.GetBytes(PrivateKey), algorithm); 
     } 

    public static string Encode(object payload, byte[] keyBytes, JwtHashAlgorithm algorithm) 
    { 
     var segments = new List<string>(); 
     var header = new { alg = algorithm.ToString(), typ = "JWT" }; 

     byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None)); 
     byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None)); 

     segments.Add(Base64UrlEncode(headerBytes)); 
     segments.Add(Base64UrlEncode(payloadBytes)); 

     var stringToSign = string.Join(".", segments); 

     var bytesToSign = Encoding.UTF8.GetBytes(stringToSign); 

     byte[] signature = HashAlgorithms[algorithm](keyBytes, bytesToSign); 
     segments.Add(Base64UrlEncode(signature)); 

     return string.Join(".", segments.ToArray()); 
    } 
     using (var wb = new WebClient()) 
     { 
      var url = "https://www.googleapis.com/oauth2/v3/token/"; 
      wb.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); 
      var data2 = new NameValueCollection(); 
      data2["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer"; 
      data2["assertion"] = signedJwt; 
      var response2 = wb.UploadValues(url, "POST", data2); 
     } 

Теперь после получения маркеров доступа, я стараюсь писать в свободное основание: используя следующий учебник, я видел, что я должен получить глагол: https://developers.google.com/accounts/docs/OAuth2ServiceAccount#creatinganaccount

var url = "https://www.googleapis.com/freebase/v1/mqlwrite"; 
       wb.QueryString.Add("lang", "/lang/en"); 
       wb.QueryString.Add("query", "%5B%7B%0A%20%20%22mid%22%3A%20%22%2Fm%2F011840dm%22%2C%0A%20%20%22%2Fcommon%2Ftopic%2Ftopic_equivalent_webpage%22%3A%20%7B%0A%20%20%20%20%22connect%22%3A%20%22insert%22%2C%0A%20%20%20%20%22value%22%3A%20%22http%3A%2F%2Fwww.imdb.com%2Fname%2Fnm4963898%2F%22%0A%20%20%7D%0A%7D%5D"); 
       wb.Headers.Add("Authorization", "Bearer " + accesstoken); 
       var ResponseBytes = wb.DownloadString(url); 

Ценит help :)

ответ

2

Вы включаете Content-Type в данные POST, но должны быть представлены как часть HTTP-заголовков, как в:

wb.Headers.Add("Content-Type","application/x-www-form-urlencoded"); 

Однако, используя UploadValues, это будет значение по умолчанию, если оно не переопределено.

Кроме того, UploadValues ​​автоматически кодирует ваши значения URL, поэтому вы должны представить их в своей исходной форме; поэтому для данного типа гранта, который будет означать:

data2["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer"; 

edit1:
Кроме того, ваш JWT использует неправильный aud требование, так как он установлен в https://accounts.google.com/o/oauth2/token вместо https://www.googleapis.com/oauth2/v3/token и истек 2 июля 2012 года

Edit2: Вы также должны опубликовать URL-адрес без завершающей косой черты и получить правильные метки времени и exp. Успешно протестированный код с использованием Newtonsoft.Json:

public class GoogleServiceAccountBearerJWTSample 
{ 
    private static string Base64UrlEncode(byte[] input) 
    { 
     var output = Convert.ToBase64String(input); 
     output = output.Split('=')[0]; // Remove any trailing '='s 
     output = output.Replace('+', '-'); // 62nd char of encoding 
     output = output.Replace('/', '_'); // 63rd char of encoding 
     return output; 
    } 

    public static string Encode(object payload, AsymmetricAlgorithm rsa) { 
     var segments = new List<string>(); 
     var header = new { alg = "RS256", typ = "JWT" }; 
     byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None)); 
     byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None)); 
     segments.Add(Base64UrlEncode(headerBytes)); 
     segments.Add(Base64UrlEncode(payloadBytes)); 
     var stringToSign = string.Join(".", segments.ToArray()); 
     var bytesToSign = Encoding.UTF8.GetBytes(stringToSign); 

     // VARIANT A - should work on non-SHA256 enabled systems 
     var rs = rsa as RSACryptoServiceProvider; 
     var cspParam = new CspParameters 
     { 
      KeyContainerName = rs.CspKeyContainerInfo.KeyContainerName, 
      KeyNumber = rs.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2 
     }; 
     var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false }; 
     var signature = aescsp.SignData(bytesToSign, "SHA256"); 
     // END OF VARIANT A 

     // VARIANT B - works on FIPS SHA256 enabled systems 
     // var pkcs1 = new RSAPKCS1SignatureFormatter(rsa); 
     // pkcs1.SetHashAlgorithm("SHA256"); 
     // var signature = pkcs1.CreateSignature(new SHA256Managed().ComputeHash(bytesToSign)); 
     // END OF VARIANT B 

     segments.Add(Base64UrlEncode(signature)); 
     return string.Join(".", segments.ToArray()); 
    } 

    public static void Main() 
    {  
     var utc0 = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc); 
     var issueTime = DateTime.UtcNow; 

     var iat = (int)issueTime.Subtract(utc0).TotalSeconds; 
     var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; // Expiration time is up to 1 hour, but lets play on safe side 

     var payload = new { 
      iss = "[email protected]", 
      aud = "https://www.googleapis.com/oauth2/v3/token", 
      scope = "https://www.googleapis.com/auth/freebase", 
      exp = exp, 
      iat = iat 
     }; 

     var certificate = new X509Certificate2("google-client.p12", "notasecret"); 
     var signedJwt = Encode(payload, certificate.PrivateKey); 

     //System.Console.WriteLine(signedJwt); 

     using (var wb = new WebClient()) 
     { 
      var url = "https://www.googleapis.com/oauth2/v3/token"; 
      var data2 = new NameValueCollection(); 
      data2["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer"; 
      data2["assertion"] = signedJwt; 
      var response2 = wb.UploadValues(url, "POST", data2); 
      System.Console.WriteLine(Encoding.UTF8.GetString(response2)); 
     } 
    } 
} 
+0

Благодарим за отзыв. Я изменил свой код, как вы предложили (как вы можете видеть выше), но, к сожалению, все еще получает ошибку «400 Bad Request». Что я делаю неправильно? – user2051871

+0

Хороший вопрос! Имейте то же самое, задаваясь вопросом, что делать. –

+0

см. Добавление ответа –