I have been following this tutorial to include Google Sign-in support to my Desktop app. The library I'm using is this one.
Everything works and this is the implementation of the authorize()
method:
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;
}
However, from a Credential
object, I can only retrieve the access token by calling Credential.getAccessToken()
, but what I need is the id token
. How can I retrieve the id_token from the user after it's been authenticated?
To get an ID token, you need to request them when authenticating users. Auth0 makes it easy for your app to authenticate users using: Quickstarts: The easiest way to implement authentication, which can show you how to use Universal Login, the Lock widget, and Auth0's language and framework-specific SDKs.
Obtaining an Access Token by Using the User Credentials Without a Client Assertion. Using the resource owner password credentials workflow, the OAuth client can obtain an access token by providing the user's credentials (that is the user name and password).
The ID token is a JSON web token (JWT) that contains claims about the identity of the authenticated user, such as name , email , and phone_number . You can use this identity information inside your application. The ID token can also be used to authenticate users to your resource servers or server applications.
After you add the authorization profile, you need to get access token from the server. In this tutorial, we get it by using the Authorization Code grant method: Click Get Token. In the subsequent dialog, enter Client Identification and Secret, Authorization URI, Access Token URI and Redirect URI.
I literally figured it out after starting the bounty! It's possible to get the Id Token by inheriting from AuthorizedCodeInstalledApp
and providing your own implementation of authorize()
Here's what I did...
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();
}
}
}
After you do that, instead of
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
Use:
Credential credential = new GoogleAuthCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
This solution I found works by adding a CredentialCreatedListener
and a CredentialRefreshListener
inside our GoogleAuthorizationCodeFlow.Builder
.
Here's the sample code:
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;
}
The code is pretty much self-explanatory. Whenever a new Credential
is created or refreshed by calling credential.refreshToken()
, the listeners will be notified and the id_token
will be taken from the TokenResponse
(which is actually a GoogleTokenResponse
object that contains an id_token
field), and we'll use the default DataStoreFactory
to save the id_token
. The id_token
will now be persisted locally, and will be automatically updated by the listeners whenever credential.refreshToken()
is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With