3

我有一个关于使用 JWT 为 Google Analytics 获取刷新令牌的问题。

请参考以下运行良好的示例代码,我可以获取 Analytics 对象,使用它我可以访问 Analytics 数据。

        GoogleCredential credentialGA = new GoogleCredential.Builder().setTransport(httpTransport)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId("$#$@#$#$#$@developer.gserviceaccount.com")
                .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();

如果我调用credentialGA.getAccessToken()它会返回一个字符串。但是调用 credentialGA.getRefreshToken() 它总是返回 null。现在按照俗话说,如果我必须使用此 Analytics 对象进行进一步调用,我需要拥有刷新令牌,使用它我可以再次创建 GoogleCredential 对象以获取 Analytics 对象。

所以我按照https://developers.google.com/accounts/docs/OAuth2ServiceAccount中提到的步骤创建了一个 JWT 。然后,此 JWT 将用于进行刷新令牌调用。此链接上共享的示例解释了如何通过 servlet/jsp/http 使其成为可能。 https://code.google.com/p/gwdg-java/source/browse/src/java/com/google/iapsample/?r=a52c4e72381b1fc959053e3a1fc8c585ae2d7112

是否有任何示例代码可以解释使用 Java Standalone 应用程序使用 JWT 实现刷新令牌调用的相同任务。

提前致谢。

问候, 普拉塔梅什

生成 JWT 的代码:

    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());

        Enumeration<String> aliases = myStore.aliases();
        String alias = "";       
        Enumeration objEnumeration = myStore.aliases();
        while (objEnumeration.hasMoreElements() == true) {
            alias = (String) objEnumeration.nextElement();

            privateKey = (PrivateKey) myStore.getKey(alias,
                    "notasecret".toCharArray());
            if(privateKey != null){
            System.out.println("PRIVATE KEY:" + privateKey.toString());
            }
        }

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

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

    JsonObject claim = new JsonObject();
    claim.addProperty("iss", "%^@%@^%$%@developer.gserviceaccount.com");
    claim.addProperty("scope", "https://www.googleapis.com/auth/devstorage.readonly");
    claim.addProperty("aud", "https://accounts.google.com/o/oauth2/token");
    claim.addProperty("exp", "1384497516");
    claim.addProperty("iat", "1384597516");     
    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);         
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(inputStr.getBytes(UTF8_CHARSET));      

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

然后将此 JWT 字符串复制并在另一个程序员中用于请求刷新令牌,如下所示:

    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost("<link i have posted in the comment>");
    try {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
        nameValuePairs.add(new BasicNameValuePair("grant_type",
                "urn:ietf:params:oauth:grant-type:jwt-bearer"));
        nameValuePairs.add(new BasicNameValuePair("assertion",
                "<JWT Calculated earlier>"));
        post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = client.execute(post);
        BufferedReader rd = new BufferedReader(new InputStreamReader(
                response.getEntity().getContent()));

        String line = "";
        while ((line = rd.readLine()) != null) {
            System.out.println(line);
            if (line.startsWith("Auth=")) {
                String key = line.substring(5);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
4

2 回答 2

1

成功调用 API 真正需要的是访问令牌。对于服务帐户,您可以通过使用私钥签署 JWT 并将其发送到 accounts.google.com 来获得访问令牌。

看起来您上面的代码应该可以做到这一点。

刷新令牌是一锅不同的鱼。这是在最终用户授权您的应用程序访问他们的数据后,Google 将向您的应用程序提供的东西。与上面的私钥类似,它可用于获取访问令牌,然后可用于后续 API 调用。

简而言之,对于服务帐户用例(代码片段显示的内容),您根本不需要查看刷新令牌。你具体想做什么?

于 2013-11-14T17:25:11.957 回答
0

我认为您可以通过调用来检查 accessToken 的有效性

https://www.googleapis.com/oauth2/v1/tokeninfo?access_token={accessToken} 

端点并再次创建 JWT 并获取 accessToken。

于 2016-03-09T18:15:37.377 回答