Создание веб-токена JSON в Java

Я пытаюсь создать веб-токен JSON, чтобы использовать его для вызова токена обновления с доступом к API Google Analytics. Я использовал подход служебной учетной записи.

В соответствии с этим подходом мне нужно:

  1. Создать учетную запись службы
  2. Добавьте адрес электронной почты, созданный для приложения Analytics, с учетной записью Google Analytics.
  3. Загрузите файл закрытого ключа (.p12)
  4. Используйте этот закрытый ключ и адрес электронной почты для создания JWT, который впоследствии будет использоваться для вызова HTTP POST на сервер аутентификации Google, чтобы получить токен обновления.

Я не уверен, правильный ли мой подход к созданию JWT. В образце, доступном как JWT_Handler.java на сайте Google Code, рассказывается о создании JWT с частью утверждения и полезных данных запроса только с отсутствующими частями заголовка и подписи. Это сбивает с толку рекомендации Google по созданию JWT для токена обновления, где JWT состоит из трех частей:

  1. JWT-заголовок
  2. Претензия JWT
  3. Подпись

Все три части имеют кодировку Base64Url. Я пробовал следующий код:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Calendar;
import java.util.Enumeration;

import com.google.api.client.util.Base64;
import com.google.gson.JsonObject;
public class TestJWT {

private final static Charset UTF8_CHARSET = Charset.forName("UTF-8");
private static KeyStore myStore = null;
private static FileInputStream in_cert = null;
public static void main(String[] args) {
    PrivateKey privateKey = null;       
    try {
        in_cert = new FileInputStream(
                "D://Google Analytics//ClientLogin//Analytics//%$%%$%$%-privatekey.p12");

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }       
    try {
        myStore = KeyStore.getInstance("PKCS12");
        myStore.load(in_cert, "notasecret".toCharArray());
        String alias = "";       
        Enumeration objEnumeration = myStore.aliases();
        while (objEnumeration.hasMoreElements() == true) {
            alias = (String) objEnumeration.nextElement();              
            privateKey = (PrivateKey) myStore.getKey(alias,
                    "notasecret".toCharArray());
        }
    } catch (Exception e1) {
        e1.printStackTrace();
    }

    JsonObject header = new JsonObject();
    header.addProperty("alg", "RS256");
    header.addProperty("typ", "JWT");

    Calendar cal = Calendar.getInstance();      
    cal.set(1970, 01, 01);      
    String iat = Long.toString((System.currentTimeMillis() - cal.getTimeInMillis())/1000);
    String exp = Long.toString((System.currentTimeMillis() - cal.getTimeInMillis())/1000 + 60000L);

    JsonObject claim = new JsonObject();
    claim.addProperty("iss", "$$%$^%&^!%@#[email protected]");
    claim.addProperty("scope", "https://www.googleapis.com/auth/devstorage.readonly");
    claim.addProperty("aud", "https://accounts.google.com/o/oauth2/token");
    claim.addProperty("access_type", "offline");
    claim.addProperty("exp", exp);
    claim.addProperty("iat", iat);


    System.out.println("Header : " + header);
    String headerStr = header.toString();
    System.out.println("claim : " + claim);
    String claimStr = claim.toString();


    try {

        byte[] headerArr = headerStr.getBytes(UTF8_CHARSET);
        System.out.println(Base64.encodeBase64String(headerArr));

        byte[] claimArr = claimStr.getBytes(UTF8_CHARSET);
        System.out.println(Base64.encodeBase64String(claimArr));

        String inputStr = Base64.encodeBase64String(headerArr) + "." + Base64.encodeBase64String(claimArr);

        System.out.println("Input String : " + inputStr);
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(inputStr.getBytes(UTF8_CHARSET));
        System.out.println("Sign : " + signature.sign());

        System.out.println("Base64url encoded sign : " + Base64.encodeBase64String(signature.sign()));

        System.out.println("Final JWT : " + Base64.encodeBase64String(headerArr) + "." + Base64.encodeBase64String(claimArr) + "." + Base64.encodeBase64String(signature.sign()));

    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

person prathamesh_mb    schedule 15.11.2013    source источник


Ответы (1)


Пратамеш, это тот же вопрос, что и в вашем другом посте? (Запрос токена обновления в Java с JWT через отдельное приложение — не веб-приложение)

Чтобы уточнить, подписание JWT с использованием файла P12 позволит вам получить токен доступа (а не токен обновления). Это нормально, потому что токен доступа — это то, что вам нужно для последующего вызова API.

Я настоятельно рекомендую использовать клиентскую библиотеку Google Java для создания JWT и выполнения подписи, хороший пример которой вы уже вставили в другой пост:

GoogleCredential credentialGA = new GoogleCredential.Builder().setTransport(httpTransport)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId("$#$@#$#$#[email protected]")
        .setServiceAccountScopes(Collections.singleton(AnalyticsScopes.ANALYTICS_READONLY))
        .setServiceAccountPrivateKeyFromP12File(new File("$#$#$%$%$%$-privatekey.p12"))
        .build();
this.analytics = new Analytics.Builder(httpTransport, JSON_FACTORY, credentialGA).setApplicationName("Demo App").build();

Есть ли конкретная причина, по которой вы не хотите использовать клиентскую библиотеку? Он позаботится о создании JWT, его подписании, отправке, создании запросов на обслуживание, добавлении заголовков авторизации, обновлении токена доступа по истечении срока его действия и т. д. и т. д.

person aeijdenberg    schedule 15.11.2013
comment
Честно говоря, у меня не было примера кода для поиска или документа по использованию API для использования клиентской библиотеки Google для создания JWT. У меня есть пример для создания JWT в случае Google Wallet. В этом примере не показано создание JWT с заголовком для конкретного API Google Analytics. Именно по этой причине мне пришлось прибегнуть к созданию этого примера кода. У меня была большая проблема с получением токена обновления, и я думал, что создание подписанного JWT было первым шагом. В другом потоке рассказывается о моей более серьезной проблеме. Извините, если создал путаницу. - person prathamesh_mb; 18.11.2013
comment
Но все же был бы признателен за руководство по созданию подписанного JWT для Google Analytics. - person prathamesh_mb; 18.11.2013
comment
Хорошо, я думаю, что могу увидеть, где путаница. Вы должны иметь возможность использовать один и тот же код для создания подписанного JWT независимо от того, к какому API Google вы пытаетесь получить доступ. Ключевое отличие заключается в изменении запрашиваемых вами областей действия, что, похоже, вы уже сделали. Можете ли вы подтвердить, работает ли приведенный выше код для вас? (И если нет, то какую ошибку вы получаете?) - person aeijdenberg; 18.11.2013
comment
Одно быстрое замечание: используйте encodeBase64URLSafeString вместо encodeBase64String. - person Pratap Singh; 29.12.2018