Hide

Using OAuth 2.0 for Login (early version)

Sign-In with Google

Google APIs use OAuth 2.0 for authentication and authorization. You can also choose to use Google's authentication system as a way to outsource user authentication for your application. This can remove the need to create, maintain, and secure a username and password store.

The Google endpoints described in this document align with the OpenID Connect specification, which at the time of this writing was in early draft stage. For information about Google's current OAuth 2.0 implementation, see Using OAuth 2.0 for Login (OpenID Connect).

Contents

  1. Overview (deprecated)
  2. Simple example (deprecated)
  3. Forming the URL (deprecated)
  4. Validating the token (deprecated)
  5. Obtaining user profile information (deprecated)

Overview (deprecated)

During application registration you created a client_id, one or more redirect_uri, and a client_secret. When forming the request URL, you will need the client_id and redirect_uri, as well as the type of application you are writing (e.g. web server, JavaScript, device, installed application, etc.). Requesting an access token is fairly straightforward: point a browser (pop-up, or full page redirect if needed) to a Google URL and include a set of query string parameters.

Upon receipt of this request, the Google Authorization Server selects the correct active session (if the user has previously logged in with multiple identities), accepts and validates the user credentials and one-time-passwords (if the account requires it), obtains user consent for the requested permissions, and also mints and returns a response to your application. The contents of this response depend on the type of application you are writing. For web server applications, the response is an authorization code which can be exchanged for an access token and (optionally) a refresh token. For client-side applications, the response is an access token.

After obtaining an access token, your application can use that access token to make a web service request to a Google API endpoint that provides profile information about the user. When a user returns to your site, the interaction is repeated, but the user is not prompted for consent unless your application explicitly asks for it.

Simple example (deprecated)

The following is an example of an access token request URL. Note that it is just a URL that contains a set of query parameters. When you click on the link, a popup appears. If you have an active session with Google, you'll see a consent screen. If you have no active session with Google, you will see a login page, then a consent screen. If you have multiple active sessions, you will see a session selector page, then a consent screen.

If you grant the application permission, the window will be redirected to the site, and the site will be able to obtain your profile information. In this example, the site simply shows your profile information on the page and does not save it.


https://accounts.google.com/o/oauth2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&
state=%2Fprofile&
redirect_uri=https%3A%2F%2Foauth2-login-demo.appspot.com%2Foauthcallback&
response_type=token&
client_id=812741506391.apps.googleusercontent.com

If your repeat this process, you will not see the consent screen. Google remembers your consent, and simply issues a new access token to the site. If, for some reason, you'd like to reprompt the user for consent, you can add approval_prompt=force to the parameters in the request.

Forming the URL (deprecated)

The URL used when authenticating a user is https://accounts.google.com/o/oauth2/auth. This endpoint is accessible over SSL, and HTTP connections are refused.

Endpoint Description
https://accounts.google.com/o/oauth2/auth This endpoint is the target of the initial request for an access token. It handles active session lookup, authenticating the user, and user consent. The result of requests of this endpoint include access tokens, refresh tokens, and authorization codes.

The set of query string parameters supported by the Google Authorization Server are:

Parameter Values Description
response_type code or token Determines if the Google Authorization Server returns an authorization code, or an opaque access token.
client_id the client_id obtained from the Google Developers Console Indicates the client that is making the request. The value passed in this parameter must exactly match the value shown in the Google Developers Console.
redirect_uri one of your redirect_uris registered at the Google Developers Console Determines where the response is sent. The value of this parameter must exactly match one of the values registered in the Google Developers Console (including the http or https schemes, case, and trailing '/').
scope space delimited set of permissions the application requests Indicates the Google API access your application is requesting. The values passed in this parameter inform the consent page shown to the user. There is an inverse relationship between the number of permissions requested and the likelihood of obtaining user consent.
state any string This optional parameter indicates any state which may be useful to your application upon receipt of the response. The Google Authorization Server roundtrips this parameter, so your application receives the same value it sent. Possible uses include redirecting the user to the correct resource in your site, nonces, and cross-site-request-forgery mitigations.

The response_type parameter

The value of this parameter determines which OAuth 2.0 flow will be used and impacts the processing your application will need to perform. The following is a general set of guidelines to help determine which OAuth 2.0 flow is right for your application:

  • If your application requires long-running access to user data through a Google API without the user being present, then use code.
  • If your application is primarily using server side or installed application components, then use code.
  • If you're writing a JavaScript-heavy application, then use token.

For more information on using OAuth 2.0 for a specific type of application, see the appropriate documentation (Server-side, Client-side, Installed, Devices)

The scope parameter

In OAuth 2.0, the permissions your application requests are expressed in the scope parameter. Your application can include many scopes in a single token request. Before a successful response, the user views a consent dialog which informs them of the permissions your application is requesting and asks if the user is willing to explicitly grant those permissions to your application. Successful responses imply that the user has granted your application the requested permissions. Error responses can indicate a user has declined to grant your application the requested permissions or there was a problem with the token request.

Note: If your application is asking for many permissions, the consent dialog will contain many lines of text describing what your application is asking for. The more permissions your application requests, the less likely the user will be to grant your application those permissions. As a general rule, your application should only ask for the permissions it needs.

Scopes for user profile permission

There are two scopes that grant your application read-only permission to the user's basic profile information and the user's email address.

Scope Value Description
https://www.googleapis.com/auth/userinfo.profile Gain read-only access to basic profile information, including a user identifier, name, profile photo, profile URL, country, language, timezone, and birthdate.
https://www.googleapis.com/auth/userinfo.email Gain read-only access to the user's email address.

Consent page experience

When both of these scopes are present in the request, a consent dialog is shown to the user.

Handling the response (deprecated)

The response will be sent to the redirect_uri sent in an access token request. The contents and format of the response is determined by the value of the response_type parameter.

The value of the response_type parameter determines how the response is sent to your application when the user grants your application the requested permissions. A value of code indicates whether the response is sent to the web server at that address. A value of token indicates that the response is sent to client-side script.

Web server responses

Google returns an authorization code to your application if the user grants your application the permissions it requested. The authorization code is returned to your application in the query string parameter code. If the state parameter was included in the request, then it is also included in the response. An example Web Server flow response is shown below:

https://oauth2-login-demo.appspot.com/oauthcallback?code={authorizationCode}

This authorization code is redeemable for an access token and a refresh token which your application can then use to make appropriate Google API calls. Redeeming the authorization code for an access token requires server side code to include the client_id and client_secret parameters. See the Web Server documentation for more details.

Note that there are limits on the number of refresh tokens that will be issued; one limit per client/user combination, and another per user across all clients. You should save refresh tokens in long-term storage and continue to use them as long as they remain valid. If your application requests too many refresh tokens, it may run into these limits, in which case older refresh tokens will stop working.

JavaScript responses

Google returns an access token to your application if the user grants your application the permissions it requested. The access token is returned to your application in the fragment as part of the access_token parameter. Since a fragment is not returned to the server, client side script must parse the fragment and extract the value of the access_token parameter.

Other parameters included in the response include expires_in and token_type. These parameters describe the lifetime of the token in seconds, and the kind of token that is being returned. If the state parameter was included in the request, then it is also included in the response.

An example User Agent flow response is shown below:

https://oauth2-login-demo.appspot.com/oauthcallback#access_token={accesstoken}&token_type=Bearer&expires_in=3600

Below is a JavaScript snippet that parses the response and returns the parameters to the server. In keeping with the example, it is hosted on the https://oauth2-login-demo.appspot.com/oauthcallback endpoint.


// First, parse the query string
var params = {}, queryString = location.hash.substring(1),
    regex = /([^&=]+)=([^&]*)/g, m;
while (m = regex.exec(queryString)) {
  params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}

// And send the token over to the server
var req = new XMLHttpRequest();
// consider using POST so query isn't logged
req.open('GET', 'https://' + window.location.host + '/catchtoken?' + queryString, true);

req.onreadystatechange = function (e) {
  if (req.readyState == 4) {
     if(req.status == 200){
       window.location = params['state']
   }
  else if(req.status == 400) {
        alert('There was an error processing the token.')
    }
    else {
      alert('something else other than 200 was returned')
    }
  }
};
req.send(null);

This code sends the parameters received on the fragment to the server using XMLHttpRequest and writes the access token to local storage in the browser. The latter is an optional step, and depends on whether or not the application requires other JavaScript code to make calls to a Google API. Also note that this code sends the parameters to the /accepttoken endpoint, and they are sent over an HTTPS channel.

Error response

The Google Authorization Server returns an error if the user did not grant your application the permissions it requested. The error is returned to the application in the query string parameter error if the web server flow is used. If the user agent flow was used, then the error is returned in the fragment. If the state parameter was included in the request, it is also present in the error response.

An example error response for the web server flow is shown below:

https://oauth2-login-demo.appspot.com/oauthcallback?error=access_denied

An example error response for the user agent flow is shown below:

https://oauth2-login-demo.appspot.com/oauthcallback#error=access_denied

Validating the token (deprecated)

If your application uses the user agent flow, it MUST validate the token. Failure to verify tokens acquired through the user agent flow make your application more vulnerable to the confused deputy problem. If your application is using the Web Server flow, then there is no need to explicitly validate the token.

You can validate a token by making a web service request to an endpoint on the Google Authorization Server and performing a string match on the results of that web service request.

TokenInfo validation

Verifying a token using the Google Authorization Server endpoint is simple. Your application includes the access token in the access_token parameter for the following endpoint:

Endpoint Description
https://www.googleapis.com/oauth2/v1/tokeninfo Accepts an access token and returns information about that access token including: which application was it issued to, the intended target of the token, the scopes the user consented to, the remaining lifetime of the token, and the user's id.

Below is an example of such a request:

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

The TokenInfo endpoint will respond with a JSON array that describes the token or an error. Below is a table of the fields included in the non-error case:

Field Description
audience The application that is the intended target of the token.
scope The space delimited set of scopes that the user consented to.
userid This field is only present if the https://www.googleapis.com/auth/userinfo.profile scope was present in the request for the access token. The value of this field is an immutable identifier for the logged-in user, and may be used when creating and managing user sessions in your application. This identifier is the same regardless of the client_id. This provides the ability to correlate profile information across multiple applications in the same organization.
expires_in The number of seconds left in the lifetime of the token.

On the wire, the response looks similar to the following:

{
  "audience":"8819981768.apps.googleusercontent.com",
  "user_id":"123456789",
  "scope":"https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
  "expires_in":436
}

Note: When verifying a token, it is critical to ensure the audience field in the response exactly matches your client_id registered in the Google Developers Console. This is the mitigation for the confused deputy issue, and it is absolutely vital to perform this step.

If the token has expired, has been tampered with, or the permissions revoked, the Google Authorization Server will respond with an error. The error surfaces as a 400 status code, and a JSON body as follows:

{"error":"invalid_token"}

By design, no additional information is given as to the reason for the failure.

Obtaining user profile information (deprecated)

After your application acquires an access token and has (if necessary) verified it, you can use that access token when making requests to a Google API. If the https://www.googleapis.com/auth/userinfo.profile scope was included in the access token request, then you may use the access token to acquire the user's basic profile information by calling the UserInfo endpoint.

Endpoint Description
https://www.googleapis.com/oauth2/v1/userinfo Returns basic user profile information, including name, userid, gender, birthdate, photo, locale, and timezone. If the https://www.googleapis.com/auth/userinfo.email scope was present in the request, then the user's email will also be present in the response. If the email has been verified, then there is also a field that indicates the email is a verified address.

The access token is sent to this endpoint in the access_token query parameter or an Authorization: Bearer HTTP header.

For example, a call to the UserInfo API using the access_token query string parameter looks like the following:

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

A call to the same API using the access token in the HTTP header looks like the following:

GET /oauth2/v1/userinfo HTTP/1.1
Authorization: Bearer {accessToken}
Host: googleapis.com

The response of this endpoint includes the fields shown below:

Field Description
id The value of this field is an immutable identifier for the logged-in user, and may be used when creating and managing user sessions in your application. This identifier is the same regardless of the client_id. This provides the ability to correlate profile information across multiple applications in the same organization. The value of this field is the same as the value of the userid field returned by the TokenInfo endpoint.
email The email address of the logged in user
verified_email A flag that indicates whether or not Google has been able to verify the email address.
name The full name of the logged in user
given_name The first name of the logged in user
family_name The last name of the logged in user
picture The URL to the user's profile picture. If the user has no public profile, this field is not included.
locale The user's registered locale. If the user has no public profile, this field is not included.
timezone the default timezone of the logged in user
gender the gender of the logged in user (other|female|male)

Note: This list will grow over time. Your application should not be written in such a way that it errors when UserInfo returns new fields.

An example of the raw JSON array returned by this endpoint is shown below:

{
 "id": "00000000000000",
 "email": "fred.example@gmail.com",
 "verified_email": true,
 "name": "Fred Example",
 "given_name": "Fred",
 "family_name": "Example",
 "picture": "https://lh5.googleusercontent.com/-2Sv-4bBMLLA/AAAAAAAAAAI/AAAAAAAAABo/bEG4kI2mG0I/photo.jpg",
 "gender": "male",
 "locale": "en-US"
}