7

I'm using Google API Java Client to manage access to Google Drive API from Google App Engine in Java.

I get a user access token and refresh token and save both in our database. Although, I think only the refresh token needs to be persistent.

How do I manage Access token expiration? What do you think of this strategy:

  • Once I have logged into my web application, I get an Access token from my refresh token and I store it in the session. How must I create a Google credential object from refresh token stored in Database?

  • When I access Drive operations, in case of expiration, I capture the 401 exception to re-create the Access Token

I have read about Credential and Credential Store but it seems it's deprecated. Now this must be used: StoredCredential. Does anyone have a sample using this new interface?

Thanks.

Kirby
  • 15,127
  • 10
  • 89
  • 104
Diego Jovanovič
  • 234
  • 3
  • 14
  • Diego, did you finally solve it? Because i'm stuck on the same exception because of expiration. – Aerox Jun 09 '14 at 22:22
  • Hi, what happens to you? ^^ – Diego Jovanovič Jun 10 '14 at 09:24
  • Hi, i would like to create a Credential object given my stored Refresh Token in my Datastore in order to refresh the AccessToken exipred without asking a new Authorization to the User (so doing that in background). I think you took a look at the example: https://developers.google.com/drive/web/examples/java because i'm using that. – Aerox Jun 10 '14 at 13:20
  • 1
    /** Rebuilt the GoogleCredential object with my old tokens */ GoogleCredential credentials = new GoogleCredential.Builder() .setClientSecrets(clientId, clientSecret) .setJsonFactory(JSON_FACTORY).setTransport(HTTP_TRANSPORT).build() .setRefreshToken(user.getOAuth2RefreshToken()).setAccessToken(user.getOAuth2AccessToken()); /** I refresh Access Token and then, I get it*/ credentials.refreshToken(); newAccess = credentials.getAccessToken(); – Diego Jovanovič Jun 11 '14 at 07:20
  • I can't tab my comment sorry :s – Diego Jovanovič Jun 11 '14 at 07:21
  • I posted an answer here http://stackoverflow.com/a/42517728/266531 that I think addresses what you are after with more detail – Kirby Feb 28 '17 at 20:08

1 Answers1

10

if you're using the Drive API library, it will handle the 401 exceptions for you, as long as you give it a credential with access and refresh token.

Here's how to build a Credential object with the StoredCredential . You can use an implementation different than MemoryDataStoreFactory :

public class ApiCredentialManager {
    private DataStore<StoredCredential> dataStore;
    
        //Put your scopes here
        public static String[] SCOPES_ARRAY = { "https://www.googleapis.com/auth/admin.directory.user" };
    
        private ApiCredentialManager() {
    
            try {
                dataStore = MemoryDataStoreFactory.getDefaultInstance().getDataStore("credentialDatastore");
            } catch (IOException e) {
                throw new RuntimeException("Unable to create in memory credential datastore", e);
            }
        }
    
        public static ApiCredentialManager getInstance() {
            if (instance == null)
                instance = new ApiCredentialManager();
    
            return instance;
        }
    
        public Credential getCredential(String username) throws Exception {
            try {
                GoogleCredential credential = new GoogleCredential.Builder()
                        .setTransport(new NetHttpTransport())
                        .setJsonFactory(new JacksonFactory())
                        .addRefreshListener(
                                new DataStoreCredentialRefreshListener(
                                        username, dataStore))
                        .build();
                
                if(dataStore.containsKey(username)){
                    StoredCredential storedCredential = dataStore.get(username);
                    credential.setAccessToken(storedCredential.getAccessToken());
                    credential.setRefreshToken(storedCredential.getRefreshToken());
                }else{
                    //Do something of your own here to obtain the access token.
                    //Most usually redirect the user to the OAuth page
                }
                
                return credential;
            } catch (GeneralSecurityException e) {
                throw new Exception("isuue while setting credentials", e);
            } catch (IOException e) {
                e.printStackTrace();
                throw new Exception("isuue while setting credentials", e);
            }
        }
        
        //Call this when you've obtained the access token and refresh token from Google
        public void saveCredential(String username, Credential credential){
            StoredCredential storedCredential = new StoredCredential();
            storedCredential.setAccessToken(credential.getAccessToken());
            storedCredential.setRefreshToken(credential.getRefreshToken());
            dataStore.set(username, storedCredential);
        }
}
E Ciotti
  • 4,740
  • 1
  • 25
  • 17
David
  • 5,481
  • 2
  • 20
  • 33
  • Hi David, does your example automatically obtain a new access token using a refresh token?...As i tried to ask in my question at http://stackoverflow.com/questions/24117748/how-to-make-a-request-for-an-access-token-using-the-refresh-token-with-google-oa but without response :-( – Aerox Jun 09 '14 at 16:50
  • @Aerox yes it does because the drive api client in java automatically refreshes the token if required. – David Jun 10 '14 at 05:38
  • Does it do in the background? without asking every time the user to allow for a new OAuth? – Aerox Jun 10 '14 at 07:36
  • 1
    Yes, assuming you've got a refresh token at the beginning. – David Jun 11 '14 at 04:36