2015-10-03 3 views
0

Я много искал в SO, просматривал множество вопросов относительно одной и той же ошибки, применял все, что они предлагали, но ничего не получилось. Отсюда и здесь.Доступ к Google oAuth, дающий недействительный параметр grant_type (неверный запрос)

Я учусь, как позвонить в Google API (скажем, API календаря Google). Я читаю учебник для разработчиков google от https://developers.google.com/identity/protocols/OAuth2ServiceAccount

Итак, я создал учетную запись службы в Google, созданных учетных данных (я хочу вызывать Google API из своего собственного приложения). После этого я создаю JWT, поместил свой JWT с закрытым ключом, совместно используемым google, и сделав звонок 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 (неверный запрос). Я пробовал то же самое из «Advanced Rest Client клиента Chrome», но результат такой же, недопустимый grant_type (Bad request).

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

Am отсутствует какой-либо предмет здесь. Пожалуйста, помогите мне

Thanks

+0

проверить эту ссылку https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtАвторизация, это может быть из-за того, что ваш сервер часы не синхронизируются с протоколом сетевого времени. – SGC

+0

Кроме того, попробуйте изменить область действия и URL-адрес на https://accounts.google.com/o/oauth2/token вместо https://www.googleapis.com/oauth2/v3/token – SGC

+0

@SGC Я не уверен как синхронизировать мой рабочий стол с NTP. В основном я попытался изменить свой часовой пояс машины на PST (и другие) и попробовал то же самое, но ничего не получилось. Я получаю тот же результат. Все работает нормально, если я звоню в API с помощью java-программы вместо REST. В соответствии с моим требованием мне нужно использовать REST –

ответ

0

Наконец-то я получил разрешение. Когда я кодирую заголовок и запрос, я делаю кодировку base64, а не base64safeURL encoidng. После замены

Base64.encodeBase64(some_data); 

с

Base64.encodeBase64URLSafe(some_data); 

во всех случаях в коде выше, все работает нормально. Я получаю токен доступа и могу попасть в google API с токеном oAuth

Смежные вопросы