Overview
Purpose: This document explains how to use the GoogleCredential utility class to do OAuth 2.0 authorization with Google services. For information about the generic OAuth 2.0 functions that we provide, see OAuth 2.0 and the Google OAuth Client Library for Java.
Summary: To access protected data stored on Google services, use OAuth 2.0 for authorization. Google APIs support OAuth 2.0 flows for different types of client applications. In all of these flows, the client application requests an access token that is associated with only your client application and the owner of the protected data being accessed. The access token is also associated with a limited scope that defines the kind of data your client application has access to (for example "Manage your tasks"). An important goal for OAuth 2.0 is to provide secure and convenient access to the protected data, while minimizing the potential impact if an access token is stolen.
The OAuth 2.0 packages in the Google API Client Library for Java are built on the general-purpose Google OAuth 2.0 Client Library for Java.
For details, see the Javadoc documentation for the following packages:
- com.google.api.client.googleapis.auth.oauth2 (from google-api-client)
- com.google.api.client.googleapis.extensions.appengine.auth.oauth2 (from google-api-client-appengine)
Google API Console
Before you can access Google APIs, you need to set up a project on the Google API Console for auth and billing purposes, whether your client is an installed application, a mobile application, a web server, or a client that runs in browser.
For instructions on setting up your credentials properly, see the API Console Help.
Credential
GoogleCredential
GoogleCredential is a thread-safe helper class for OAuth 2.0 for accessing protected resources using an access token. For example, if you already have an access token, you can make a request in the following way:
GoogleCredentialcredential=newGoogleCredential().setAccessToken(accessToken);Plusplus=newPlus.builder(newNetHttpTransport(),GsonFactory.getDefaultInstance(),credential).setApplicationName("Google-PlusSample/1.0").build();
Google App Engine identity
This alternative credential is based on the Google App Engine App Identity Java API. Unlike the credential in which a client application requests access to an end-user's data, the App Identity API provides access to the client application's own data.
Use AppIdentityCredential (from google-api-client-appengine). This credential is much simpler because Google App Engine takes care of all of the details. You only specify the OAuth 2.0 scope you need.
Example code taken from urlshortener-robots-appengine-sample:
staticUrlshortenernewUrlshortener(){AppIdentityCredentialcredential=newAppIdentityCredential(Collections.singletonList(UrlshortenerScopes.URLSHORTENER));returnnewUrlshortener.Builder(newUrlFetchTransport(),GsonFactory.getDefaultInstance(),credential).build();}
Data store
An access token typically has an expiration date of 1 hour, after which you will get an error if you try to use it. GoogleCredential takes care of automatically "refreshing" the token, which simply means getting a new access token. This is done by means of a long-lived refresh token, which is typically received along with the access token if you use the access_type=offline
parameter during the authorization code flow (see GoogleAuthorizationCodeFlow.Builder.setAccessType(String)).
Most applications will need to persist the credential's access token and/or refresh token. To persist the credential's access and/or refresh tokens, you can provide your own implementation of DataStoreFactory with StoredCredential; or you can use one of the following implementations provided by the library:
- AppEngineDataStoreFactory: persists the credential using the Google App Engine Data Store API.
- MemoryDataStoreFactory: "persists" the credential in memory, which is only useful as a short-term storage for the lifetime of the process.
- FileDataStoreFactory: persists the credential in a file.
AppEngine Users:AppEngineCredentialStore is deprecated and will be removed soon. We recommend that you use AppEngineDataStoreFactory with StoredCredential. If you have credentials stored in the old fashion, you can use the added helper methods migrateTo(AppEngineDataStoreFactory) or migrateTo(DataStore) to do the migration.
You may use DataStoreCredentialRefreshListener and set it for the credential using GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener)).
Authorization code flow
Use the authorization code flow to allow the end-user to grant your application access to their protected data on Google APIs. The protocol for this flow is specified in Authorization Code Grant.
This flow is implemented using GoogleAuthorizationCodeFlow. The steps are:
- End-user logs in to your application. You will need to associate that user with a user ID that is unique for your application.
- Call AuthorizationCodeFlow.loadCredential(String)) based on the user ID to check if the end-user's credentials are already known. If so, we're done.
- If not, call AuthorizationCodeFlow.newAuthorizationUrl() and direct the end-user's browser to an authorization page to grant your application access to their protected data.
- The Google authorization server will then redirect the browser back to the redirect URL specified by your application, along with a
code
query parameter. Use thecode
parameter to request an access token using AuthorizationCodeFlow.newTokenRequest(String)). - Use AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String)) to store and obtain a credential for accessing protected resources.
Alternatively, if you are not using GoogleAuthorizationCodeFlow, you may use the lower-level classes:
- Use DataStore.get(String) to load the credential from the store based on the user ID.
- Use GoogleAuthorizationCodeRequestUrl to direct the browser to the authorization page.
- Use AuthorizationCodeResponseUrl to process the authorization response and parse the authorization code.
- Use GoogleAuthorizationCodeTokenRequest to request an access token and possibly a refresh token.
- Create a new GoogleCredential and store it using DataStore.set(String, V).
- Access protected resources using the
GoogleCredential
. Expired access tokens will automatically be refreshed using the refresh token (if applicable). Make sure to use DataStoreCredentialRefreshListener and set it for the credential using GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener)).
When you set up your project in the Google API Console, you select among different credentials, depending on the flow you are using. For more details, see Setting up OAuth 2.0 and OAuth 2.0 Scenarios. Code snippets for each of the flows are below.
Web server applications
The protocol for this flow is explained in Using OAuth 2.0 for Web Server Applications.
This library provides servlet helper classes to significantly simplify the authorization code flow for basic use cases. You just provide concrete subclasses of AbstractAuthorizationCodeServlet and AbstractAuthorizationCodeCallbackServlet (from google-oauth-client-servlet) and add them to your web.xml file. Note that you still need to take care of user login for your web application and extract a user ID.
publicclassCalendarServletSampleextendsAbstractAuthorizationCodeServlet{@OverrideprotectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{// do stuff}@OverrideprotectedStringgetRedirectUri(HttpServletRequestreq)throwsServletException,IOException{GenericUrlurl=newGenericUrl(req.getRequestURL().toString());url.setRawPath("/oauth2callback");returnurl.build();}@OverrideprotectedAuthorizationCodeFlowinitializeFlow()throwsIOException{returnnewGoogleAuthorizationCodeFlow.Builder(newNetHttpTransport(),GsonFactory.getDefaultInstance(),"[[ENTER YOUR CLIENT ID]]","[[ENTER YOUR CLIENT SECRET]]",Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();}@OverrideprotectedStringgetUserId(HttpServletRequestreq)throwsServletException,IOException{// return user ID}}publicclassCalendarServletCallbackSampleextendsAbstractAuthorizationCodeCallbackServlet{@OverrideprotectedvoidonSuccess(HttpServletRequestreq,HttpServletResponseresp,Credentialcredential)throwsServletException,IOException{resp.sendRedirect("/");}@OverrideprotectedvoidonError(HttpServletRequestreq,HttpServletResponseresp,AuthorizationCodeResponseUrlerrorResponse)throwsServletException,IOException{// handle error}@OverrideprotectedStringgetRedirectUri(HttpServletRequestreq)throwsServletException,IOException{GenericUrlurl=newGenericUrl(req.getRequestURL().toString());url.setRawPath("/oauth2callback");returnurl.build();}@OverrideprotectedAuthorizationCodeFlowinitializeFlow()throwsIOException{returnnewGoogleAuthorizationCodeFlow.Builder(newNetHttpTransport(),GsonFactory.getDefaultInstance()"[[ENTER YOUR CLIENT ID]]","[[ENTER YOUR CLIENT SECRET]]",Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();}@OverrideprotectedStringgetUserId(HttpServletRequestreq)throwsServletException,IOException{// return user ID}}
Google App Engine applications
The authorization code flow on App Engine is almost identical to the servlet authorization code flow, except that we can leverage Google App Engine's Users Java API. The user needs to be logged in for the Users Java API to be enabled; for information about redirecting users to a login page if they are not already logged in, see Security and Authentication (in web.xml).
The primary difference from the servlet case is that you provide concrete subclasses of AbstractAppEngineAuthorizationCodeServlet and AbstractAppEngineAuthorizationCodeCallbackServlet (from google-oauth-client-appengine. They extend the abstract servlet classes and implement the getUserId
method for you using the Users Java API. AppEngineDataStoreFactory (from google-http-client-appengine) is a good option for persisting the credential using the Google App Engine Data Store API.
Example taken (slightly modified) from calendar-appengine-sample:
publicclassCalendarAppEngineSampleextendsAbstractAppEngineAuthorizationCodeServlet{@OverrideprotectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{// do stuff}@OverrideprotectedStringgetRedirectUri(HttpServletRequestreq)throwsServletException,IOException{returnUtils.getRedirectUri(req);}@OverrideprotectedAuthorizationCodeFlowinitializeFlow()throwsIOException{returnUtils.newFlow();}}classUtils{staticStringgetRedirectUri(HttpServletRequestreq){GenericUrlurl=newGenericUrl(req.getRequestURL().toString());url.setRawPath("/oauth2callback");returnurl.build();}staticGoogleAuthorizationCodeFlownewFlow()throwsIOException{returnnewGoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT,JSON_FACTORY,getClientCredential(),Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();}}publicclassOAuth2CallbackextendsAbstractAppEngineAuthorizationCodeCallbackServlet{privatestaticfinallongserialVersionUID=1L;@OverrideprotectedvoidonSuccess(HttpServletRequestreq,HttpServletResponseresp,Credentialcredential)throwsServletException,IOException{resp.sendRedirect("/");}@OverrideprotectedvoidonError(HttpServletRequestreq,HttpServletResponseresp,AuthorizationCodeResponseUrlerrorResponse)throwsServletException,IOException{Stringnickname=UserServiceFactory.getUserService().getCurrentUser().getNickname();resp.getWriter().print("<h3>"+nickname+", why don't you want to play with me?</h1>");resp.setStatus(200);resp.addHeader("Content-Type","text/html");}@OverrideprotectedStringgetRedirectUri(HttpServletRequestreq)throwsServletException,IOException{returnUtils.getRedirectUri(req);}@OverrideprotectedAuthorizationCodeFlowinitializeFlow()throwsIOException{returnUtils.newFlow();}}
For an additional sample, see storage-serviceaccount-appengine-sample.
Service accounts
GoogleCredential also supports service accounts. Unlike the credential in which a client application requests access to an end-user's data, Service Accounts provide access to the client application's own data. Your client application signs the request for an access token using a private key downloaded from the Google API Console.
Example code taken from plus-serviceaccount-cmdline-sample:
HttpTransporthttpTransport=GoogleNetHttpTransport.newTrustedTransport();JsonFactoryjsonFactory=GsonFactory.getDefaultInstance();...// Build service account credential.GoogleCredentialcredential=GoogleCredential.fromStream(newFileInputStream("MyProject-1234.json")).createScoped(Collections.singleton(PlusScopes.PLUS_ME));// Set up global Plus instance.plus=newPlus.Builder(httpTransport,jsonFactory,credential).setApplicationName(APPLICATION_NAME).build();...
For an additional sample, see storage-serviceaccount-cmdline-sample.
Impersonation
You can also use the service account flow to impersonate a user in a domain that you own. This is very similar to the service account flow above, but you additionally call GoogleCredential.Builder.setServiceAccountUser(String).
Installed applications
This is the command-line authorization code flow described in Using OAuth 2.0 for Installed Applications.
Example snippet from plus-cmdline-sample:
publicstaticvoidmain(String[]args){try{httpTransport=GoogleNetHttpTransport.newTrustedTransport();dataStoreFactory=newFileDataStoreFactory(DATA_STORE_DIR);// authorizationCredentialcredential=authorize();// set up global Plus instanceplus=newPlus.Builder(httpTransport,JSON_FACTORY,credential).setApplicationName(APPLICATION_NAME).build();// ...}privatestaticCredentialauthorize()throwsException{// load client secretsGoogleClientSecretsclientSecrets=GoogleClientSecrets.load(JSON_FACTORY,newInputStreamReader(PlusSample.class.getResourceAsStream("/client_secrets.json")));// set up authorization code flowGoogleAuthorizationCodeFlowflow=newGoogleAuthorizationCodeFlow.Builder(httpTransport,JSON_FACTORY,clientSecrets,Collections.singleton(PlusScopes.PLUS_ME)).setDataStoreFactory(dataStoreFactory).build();// authorizereturnnewAuthorizationCodeInstalledApp(flow,newLocalServerReceiver()).authorize("user");}
Client-side applications
To use the browser-based client flow described in Using OAuth 2.0 for Client-side Applications, you would typically follow these steps:
- Redirect the end user in the browser to the authorization page using GoogleBrowserClientRequestUrl to grant your browser application access to the end user's protected data.
- Use the Google API Client Library for JavaScript to process the access token found in the URL fragment at the redirect URI registered at the Google API Console.
Sample usage for a web application:
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{Stringurl=newGoogleBrowserClientRequestUrl("812741506391.apps.googleusercontent.com","https://oauth2.example.com/oauthcallback",Arrays.asList("https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile")).setState("/profile").build();response.sendRedirect(url);}
Android
Which library to use with Android:
If you are developing for Android and the Google API you want to use is included in the Google Play Services library, use that library for the best performance and experience. If the Google API you want to use with Android is not part of the Google Play Services library, you can use the Google API Client Library for Java, which supports Android 4.0 (Ice Cream Sandwich) (or higher), and which is described here. The support for Android in the Google API Client Library for Java is @Beta.
Background:
Starting with Eclair (SDK 2.1), user accounts are managed on an Android device using the Account Manager. All Android application authorization is centrally managed by the SDK using AccountManager. You specify the OAuth 2.0 scope your application needs, and it returns an access token to use.
The OAuth 2.0 scope is specified via the authTokenType
parameter as oauth2:
plus the scope. For example:
oauth2:https://www.googleapis.com/auth/tasks
This specifies read/write access to the Google Tasks API. If you need multiple OAuth 2.0 scopes, use a space-separated list.
Some APIs have special authTokenType
parameters that also work. For example, "Manage your tasks" is an alias for the authtokenType
example shown above.
You must also specify the API key from the Google API Console. Otherwise, the token that the AccountManager gives you only provides you with anonymous quota, which is usually very low. By contrast, by specifying an API key you receive a higher free quota, and can optionally set up billing for usage above that.
Example code snippet taken from tasks-android-sample:
com.google.api.services.tasks.Tasksservice;@OverridepublicvoidonCreate(BundlesavedInstanceState){credential=GoogleAccountCredential.usingOAuth2(this,Collections.singleton(TasksScopes.TASKS));SharedPreferencessettings=getPreferences(Context.MODE_PRIVATE);credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME,null));service=newcom.google.api.services.tasks.Tasks.Builder(httpTransport,jsonFactory,credential).setApplicationName("Google-TasksAndroidSample/1.0").build();}privatevoidchooseAccount(){startActivityForResult(credential.newChooseAccountIntent(),REQUEST_ACCOUNT_PICKER);}@OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){super.onActivityResult(requestCode,resultCode,data);switch(requestCode){caseREQUEST_GOOGLE_PLAY_SERVICES:if(resultCode==Activity.RESULT_OK){haveGooglePlayServices();}else{checkGooglePlayServicesAvailable();}break;caseREQUEST_AUTHORIZATION:if(resultCode==Activity.RESULT_OK){AsyncLoadTasks.run(this);}else{chooseAccount();}break;caseREQUEST_ACCOUNT_PICKER:if(resultCode==Activity.RESULT_OK&&data!=null&&data.getExtras()!=null){StringaccountName=data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);if(accountName!=null){credential.setSelectedAccountName(accountName);SharedPreferencessettings=getPreferences(Context.MODE_PRIVATE);SharedPreferences.Editoreditor=settings.edit();editor.putString(PREF_ACCOUNT_NAME,accountName);editor.commit();AsyncLoadTasks.run(this);}}break;}}