2012-08-13 38 views
12

देता है मैं सर्वर के माध्यम से सर्वर के माध्यम से अपने ऐप के सक्षम BigQuery API के साथ संवाद करने की कोशिश कर रहा हूं।Google OAuth2 सेवा खाता पहुंच टोकन अनुरोध 'अमान्य अनुरोध' प्रतिक्रिया

मैंने अपने जेडब्ल्यूटी को सर्वोत्तम रूप से सी # में बनाने के लिए इस Google guide पर सभी बक्से लगाए हैं।

और मैंने बेस 64 यूआरएल को आवश्यक सब कुछ एन्कोड किया है।

जब मैं फिडलर का उपयोग करता हूं तो मुझे वही परिणाम मिलता है। त्रुटि संदेश में निराशाजनक रूप से विस्तार की कमी है! मेरे द्वारा और क्या आजमाया जा सकता है?! यहां मेरा कोड है:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // certificate 
     var certificate = new X509Certificate2(@"<Path to my certificate>.p12", "notasecret"); 

     // header 
     var header = new { typ = "JWT", alg = "RS256" }; 

     // claimset 
     var times = GetExpiryAndIssueDate(); 
     var claimset = new 
     { 
      iss = "<email address of the client id of my app>", 
      scope = "https://www.googleapis.com/auth/bigquery", 
      aud = "https://accounts.google.com/o/oauth2/token", 
      iat = times[0], 
      exp = times[1], 
     }; 

     // encoded header 
     var headerSerialized = JsonConvert.SerializeObject(header); 
     var headerBytes = Encoding.UTF8.GetBytes(headerSerialized); 
     var headerEncoded = Base64UrlEncode(headerBytes); 

     // encoded claimset 
     var claimsetSerialized = JsonConvert.SerializeObject(claimset); 
     var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized); 
     var claimsetEncoded = Base64UrlEncode(claimsetBytes); 

     // input 
     var input = headerEncoded + "." + claimsetEncoded; 
     var inputBytes = Encoding.UTF8.GetBytes(input); 

     // signiture 
     var rsa = certificate.PrivateKey as RSACryptoServiceProvider; 
     var cspParam = new CspParameters 
     { 
      KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName, 
      KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2 
     }; 
     var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false }; 
     var signatureBytes = aescsp.SignData(inputBytes, "SHA256"); 
     var signatureEncoded = Base64UrlEncode(signatureBytes); 

     // jwt 
     var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded; 

     Console.WriteLine(jwt); 

     var client = new HttpClient(); 
     var uri = "https://accounts.google.com/o/oauth2/token"; 
     var post = new Dictionary<string, string> 
     { 
      {"assertion", jwt}, 
      {"grant_type", "urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer"} 
     }; 
     var content = new FormUrlEncodedContent(post); 
     var result = client.PostAsync(uri, content).Result; 

     Console.WriteLine(result); 
     Console.WriteLine(result.Content.ReadAsStringAsync().Result); 
     Console.ReadLine(); 
    } 

    private static int[] GetExpiryAndIssueDate() 
    { 
     var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 
     var issueTime = DateTime.Now; 

     var iat = (int)issueTime.Subtract(utc0).TotalSeconds; 
     var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; 

     return new[]{iat, exp}; 
    } 

    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; 
    } 
} 
+0

मुझे कुछ भी स्पष्ट रूप से स्पष्ट नहीं मिल रहा है, और मैंने आपके कोड की प्रत्येक पंक्ति के माध्यम से कदम रखा है। एक बात यह हो सकती है कि आप अपने शब्दकोश में अनुदान प्रकार को एन्कोड कर रहे हैं, और FormUrlEncodededContent इसे डबल-एन्कोडिंग समाप्त कर सकता है। तो, मैं कोशिश करता हूं "urn: ietf: params: oauth: अनुदान-प्रकार: jwt-bearer" इसके बजाए। –

+1

ऐसा लगता है कि एचटीपी क्लाइंट हाल ही में .NET फ्रेमवर्क रिलीज से है, इसलिए मैं इसे इंस्टॉल कर रहा हूं, और कोड को सीधे भी कोशिश कर रहा हूं। मैं कुछ लोगों के लिए भी आंतरिक रूप से पहुंचा हूं जो मदद करने में सक्षम हो सकते हैं। –

उत्तर

12

ऐसा लगता है कि उपर्युक्त टिप्पणी में मेरा अनुमान सही था। मैं बदल कर काम कर रहे अपने कोड है:

"urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer"

रहे हैं:

"urn:ietf:params:oauth:grant-type:jwt-bearer"

ऐसा लगता है कि अगर आप गलती से डबल एन्कोडिंग यह थे।

{ 
    "access_token" : "1/_5pUwJZs9a545HSeXXXXXuNGITp1XtHhZXXxxyyaacqkbc", 
    "token_type" : "Bearer", 
    "expires_in" : 3600 
} 

संपादित नोट::

मैं अब एक प्रतिक्रिया है जो तरह दिखता मिलता है अपने सर्वर पर सही दिनांक/समय/समय क्षेत्र/डीएसटी विन्यास के लिए सुनिश्चित करें। कुछ सेकंड तक घड़ी बंद होने के परिणामस्वरूप invalid_grant त्रुटि होगी। http://www.time.gov यूटीसी सहित अमेरिकी सरकार से आधिकारिक समय देगा।

5

डेटटाइम के बजाय DateTime.UtcNow का उपयोग करना सुनिश्चित करें.अब GetExpiryAndIssueDate विधि में।