web-dev-qa-db-ja.com

資格情報オブジェクトからユーザーIDトークンを取得するにはどうすればよいですか?

私は this チュートリアルに従って、デスクトップアプリにGoogleサインインサポートを含めています。私が使用しているライブラリは これ です。

すべてが機能し、これはauthorize()メソッドの実装です。

_public Credential authorize() throws IOException {
    // Load client secrets.
    InputStream in = GoogleLogin.class.getResourceAsStream("/google/client_secret.json");
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));

    // Build flow and trigger user authorization request.
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(DATA_STORE_FACTORY)
            .setAccessType("offline")
            .build();

    Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");

    System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
    return credential;
}
_

ただし、Credentialオブジェクトからは、Credential.getAccessToken()を呼び出すことによってのみアクセストークンを取得できますが、必要なのは_id token_です。認証された後、ユーザーからid_tokenを取得するにはどうすればよいですか?

17
Morgan

私は賞金を始めた後、文字通りそれを理解しました! AuthorizedCodeInstalledAppから継承し、authorize()の独自の実装を提供することで、IDトークンを取得することができます。

これが私がしたことです...

_public class GoogleAuthCodeInstalledApp extends AuthorizationCodeInstalledApp {

    public GoogleAuthCodeInstalledApp(AuthorizationCodeFlow flow, VerificationCodeReceiver receiver) {
        super(flow, receiver);
    }

    @Override
    public Credential authorize(String userId) throws IOException {
        try {
            Credential credential = getFlow().loadCredential(userId);
            if (credential != null
                    && (credential.getRefreshToken() != null
                    || credential.getExpiresInSeconds() == null
                    || credential.getExpiresInSeconds() > 60)) {
                return credential;
            }
            // open in browser
            String redirectUri = getReceiver().getRedirectUri();
            AuthorizationCodeRequestUrl authorizationUrl
                    = getFlow().newAuthorizationUrl().setRedirectUri(redirectUri);
            onAuthorization(authorizationUrl);
            // receive authorization code and exchange it for an access token
            String code = getReceiver().waitForCode();
            GoogleTokenResponse response = (GoogleTokenResponse) getFlow().newTokenRequest(code).setRedirectUri(redirectUri).execute();
            System.out.println(response.getIdToken()); //YES, THIS IS THE ID TOKEN!!!
            // store credential and return it
            return getFlow().createAndStoreCredential(response, userId);
        } finally {
            getReceiver().stop();
        }
    }

}
_

あなたがそれをした後、代わりに

_Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
_

使用する:

_Credential credential = new GoogleAuthCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
_

PDATE 2018-05-29-より良い、より信頼性の高いソリューションを見つけました

私が見つけたこのソリューションは、_GoogleAuthorizationCodeFlow.Builder_内にCredentialCreatedListenerCredentialRefreshListenerを追加することで機能します。

サンプルコードは次のとおりです。

_public Credential authorize() throws IOException {
    InputStream in = GoogleLogin.class.getResourceAsStream("/google/client_secret.json");
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
    // Build flow and trigger user authorization request.
    flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(DATA_STORE_FACTORY)
            .setAccessType("offline")
            .setCredentialCreatedListener(new AuthorizationCodeFlow.CredentialCreatedListener() {
                @Override
                public void onCredentialCreated(Credential credential, TokenResponse tokenResponse) throws IOException {
                    DATA_STORE_FACTORY.getDataStore("user").set("id_token", tokenResponse.get("id_token").toString());
                }
            })
            .addRefreshListener(new CredentialRefreshListener() {
                @Override
                public void onTokenResponse(Credential credential, TokenResponse tokenResponse) throws IOException {
                    DATA_STORE_FACTORY.getDataStore("user").set("id_token", tokenResponse.get("id_token").toString());
                }

                @Override
                public void onTokenErrorResponse(Credential credential, TokenErrorResponse tokenErrorResponse) throws IOException {
                    //handle token error response
                }
            })
            .build();

    Credential credential = new AuthorizationCodeInstalledApp(flow, serverReceiver).authorize("user");
    System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
    return credential;
}
_

コードはほとんど自明です。 credential.refreshToken()を呼び出して新しいCredentialが作成または更新されるたびに、リスナーに通知され、_id_token_がTokenResponseから取得されます(実際には_id_token_フィールドを含むGoogleTokenResponseオブジェクト)。デフォルトのDataStoreFactoryを使用して_id_token_を保存します。 _id_token_はローカルで永続化され、credential.refreshToken()が呼び出されるたびにリスナーによって自動的に更新されます。

10
Morgan