2015-10-03 36 views
0

我在SO搜索了很多,瀏覽了許多關於同一個錯誤的問題,應用了他們建議的任何內容,但沒有結果。因此寫在這裏。訪問谷歌oAuth給無效grant_type(壞請求)

我正在學習如何撥打Google API(例如Google Calendar API)。我正在通過谷歌開發人員教程從 ​​

所以我創建了一個服務帳戶在谷歌創建的憑據(我想從我自己的應用程序調用Google API)。之後我創建了JWT,用谷歌共享的私鑰給我的JWT打了一針,並且發起了REST POST調用來獲得oAuth。這裏是我的代碼

public class TestGoogleAPI { 

public static void main(String[] args) throws Exception{ 
    String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; 
    long time = Calendar.getInstance().getTimeInMillis()/1000; 

    String claimSet = "{\"iss\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com\"," + 
       "\"scope\":\"https://www.googleapis.com/auth/calendar\"," + 
       "\"aud\":\"https://www.googleapis.com/oauth2/v3/token\"," + 
       "\"exp\":"+ (time+3600) +"," + 
       "\"iat\":" + time +"}"; 


    String base64Header = new String(Base64.encodeBase64(header.getBytes()),"UTF-8"); 
    String base64ClaimSet = new String(Base64.encodeBase64(claimSet.getBytes()),"UTF-8"); 

    String input = base64Header + "." + base64ClaimSet; 

    File f = new File("D:/downloads/privatekey.txt"); 
    FileInputStream fis = new FileInputStream(f); 
    DataInputStream dis = new DataInputStream(fis); 
    byte[] keyBytes = new byte[(int)f.length()]; 
    dis.readFully(keyBytes); 
    dis.close(); 
    byte[] key = Base64.decodeBase64(keyBytes); 

    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key); 
    KeyFactory kf = KeyFactory.getInstance("RSA"); 
    PrivateKey privatekey = kf.generatePrivate(spec); 

    Signature signature = Signature.getInstance("SHA256withRSA"); 
    signature.initSign(privatekey); 
    signature.update(input.getBytes()); 
    String base64Sign = new String(Base64.encodeBase64(signature.sign()),"UTF-8"); 

    doHttpPost("https://www.googleapis.com/oauth2/v3/token", input + "." + base64Sign); 
} 

public static void doHttpPost(String urlStr, String assertion) throws Exception{ 
    URL url = new URL(urlStr); 
     HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
     conn.setRequestMethod("POST"); 
     conn.setDoOutput(true); 
     conn.setDoInput(true); 
     conn.setUseCaches(false); 
     conn.setAllowUserInteraction(false); 
     conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 

     OutputStream out = conn.getOutputStream(); 
     Writer writer = new OutputStreamWriter(out, "UTF-8"); 
     writer.write("grant_type"); 
     writer.write("="); 
     writer.write(URLEncoder.encode("urn:ietf:params:oauth:grant-type:jwt-bearer", "UTF-8")); 
     writer.write("&"); 
     writer.write("assertion"); 
     writer.write("="); 
     writer.write(URLEncoder.encode(assertion, "UTF-8")); 
     writer.close(); 
     out.close(); 

     if (conn.getResponseCode() != 200) { 
      System.out.println(conn.getResponseMessage()); 
     } 

     BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
     StringBuilder sb = new StringBuilder(); 
     String line; 
     while ((line = rd.readLine()) != null) { 
     sb.append(line); 
     } 
     rd.close(); 

     conn.disconnect(); 
     System.out.println(sb.toString()); 
} 

} 

我得到400(壞請求)。我試過「Chrome的高級休息客戶端」,但結果是一樣的,無效的grant_type(錯誤的請求)。

{ 
    error: "invalid_grant" 
    error_description: "Bad Request" 
} 

我是否在這裏遺漏任何東西。請幫我

謝謝

+0

檢查此鏈接https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization,這可能是因爲您的服務器時鐘與網絡時間協議不同步。 – SGC

+0

此外,請嘗試將您的範圍和網址更改爲 https://accounts.google.com/o/oauth2/token,而不是https://www.googleapis.com/oauth2/v3/token – SGC

+0

@SGC我不確定如何將我的桌面與NTP同步。基本上我試着改變我的機器時區到PST(和其他人),並嘗試相同的,但沒有結果。我得到了同樣的結果。如果我使用java程序調用API而不是使用REST,那麼一切正常。根據我的要求,我需要使用REST –

回答

0

最後我得到了決議。當我編碼頭文件和聲明集時,我正在執行base64編碼,而不是base64safeURL encoidng。在上面的代碼與

Base64.encodeBase64URLSafe(some_data); 

在所有情況下更換

Base64.encodeBase64(some_data); 

之後,一切工作正常。我得到訪問令牌,並能夠通過oAuth令牌訪問谷歌API