Using OAuth 2.0 for Mobile and Desktop Applications

Our standards-based OAuth 2.0 endpoints support applications installed on devices such as computers, phones, and tablets. Installed apps are distributed to individual devices, and as such it is assumed they cannot keep secrets. They may access user data APIs while the user is present, or when running in the background.

If you are writing an app for iOS or Android, you may prefer to use Google Sign-in. The Google Sign-in client libraries provide Sign-in and OAuth functionality, and may be simpler to configure and use than the lower-level OAuth protocol described here.

If your app runs on a device without access to a system browser, or with only limited input capabilities (for example, TVs, video cameras, or printers), see Using OAuth 2.0 for TVs & Devices.

Libraries and Samples

We recommend the following libraries and samples to get you going faster with the techniques described in this document.


Using OAuth 2.0 for Apps is similar to using OAuth 2.0 for websites. The difference compared with Web-based clients is that the app needs to open the system browser (embedded webviews are strongly discouraged) and supply a local Redirect URI on which it can receive the authorization code. Unlike with web clients, the OAuth 2.0 client secret (if used) is assumed not to be confidential. If you are new to OAuth, it is recommended to first read through our general OAuth documentation.

Choosing a Redirect Method and Registering your Client

The redirect URI specified in the request determines how the authorization code is returned to your application. There are several options available to installed apps for receiving the authorization code, the availability and user experience of which varies by platform.

Custom URI Scheme

Redirect URI, where is the reverse DNS notation of a domain under your control. The custom scheme must contain a period to be valid. You may append an optional path component (e.g. Note the single "/" after the custom URI scheme, which is different from regular HTTP URLs
Recommended Usage iOS Apps, Android Apps, Universal Windows Platform (UWP) apps.
Client Type Register with type Android for an Android app, otherwise choose iOS. When registering your client, the package name or bundle id is the custom URI scheme used in the redirect (e.g. For UWP apps, the scheme cannot exceed 39 characters in length.

Your app must register with the system for the custom URI scheme in order to receive the authorization response. How your app registers its custom URI scheme varies by platform. Our libraries and samples demonstrate some platform-specific implementations of custom URI scheme redirects.

Loopback IP Address

Redirect URI or http://[::1]:port. You should query your platform for the relevant loopback IP, and start an HTTP listener on a random available port, . Substitute port for the actual port number you are listening on.
Recommended Usage macOS, Linux, and Windows desktop (but not Universal Windows Platform) apps.
Client Type Register with type Other.

To receive the authorization code using this URL, your application must be listening on the local web server. This is possible on many, but not all, platforms. If your platform supports it this is the recommended mechanism for obtaining the authorization code.

When your app receives the authorization response, for best usability, it should respond with an HTML page, instructing the user to close the browser tab and return to your app.

Note: It is also possible to use localhost in place of the loopback IP, but this may cause issues with client firewalls. Most firewalls allow loopback communication, though this may not always be the case.

Constructing the Authorization Request URL

The URL to use when authenticating a user is This endpoint is accessible over SSL, and HTTP (non-SSL) connections are refused.

Endpoint Description This endpoint is the target of the initial request. It handles active session lookup, authenticating the user, and user consent. When your application sends a request to this endpoint, the response includes an access token, a refresh token, and an authorization code.

The query string parameters supported by the Google Authorization Server for installed applications are:

Parameter Values Description
response_type code For installed applications, use a value of code, indicating that the Google OAuth 2.0 endpoint should return an authorization code.
client_id The client ID you obtain from the API Console. Identifies the client that is making the request. The value passed in this parameter must exactly match the value shown in the Google API Console.
redirect_uri, Determines how the response is sent to your app. See Choosing a redirect URI to determine the correct value to use.
scope Space-delimited set of scope strings. Identifies the Google API access that your application is requesting. The values passed in this parameter inform the consent screen that is shown to the user. There may be an inverse relationship between the number of permissions requested and the likelihood of obtaining user consent. For information about available login scopes, see Login scopes. To see the available scopes for all Google APIs, visit the APIs Explorer.
state Any string. Provides any state information that might 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.
login_hint email address or sub identifier When your application knows which user it is trying to authenticate, it can provide this parameter as a hint to the Authentication Server. Passing this hint will either pre-fill the email box on the sign-in form or select the proper multi-login session, thereby simplifying the login flow.

Note: Due to the fact the client is not confidential, you cannot do incremental authorization with mobile and desktop apps.

Example URL

An example URL is shown below, with line breaks and spaces for readability.

A second example URL, with line breaks and spaces for readability.

The difference between these two URLs is the redirect_uri parameter. The first one results in an authorization code sent to a local HTTP listener. The second one results in the authorization code sent to a custom URI scheme claimed by the app.

Handling the response and exchanging the code

How your app receives the authorization URL depends on which Redirect URI you use. See the respective Redirect URI docs for information regarding receiving the code.

Once your app has received the authorization response, it will includes the authorization code (code), or an error (error) such as error=access_denied if the user declined the request.

For successful responses, you can exchange the code for an access token and a refresh token. To make this token request, send an HTTP POST request to the /oauth2/v4/token endpoint, and include the following parameters:

Field Description
code The authorization code returned from the initial request.
client_id The client ID you obtained from the Google API Console.
client_secret The client secret you obtained from the API Console (not applicable for clients registered as Android, iOS or Chrome applications).
redirect_uri The redirect URI you obtained from the API Console.
grant_type As defined in the OAuth 2.0 specification, this field must contain a value of authorization_code.

The actual request might look like the following:

POST /oauth2/v4/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded


A successful response to this request contains the following fields:

Field Description
access_token The token that can be sent to a Google API.
id_token A JWT that contains identity information about the user that is digitally signed by Google. If your request included an identity scope such as openid, profile, or email.
refresh_token A token that may be used to obtain a new access token, included by default for installed applications. Refresh tokens are valid until the user revokes access.
expires_in The remaining lifetime of the access token.
token_type Identifies the type of token returned. Currently, this field always has the value Bearer.

Note: Other fields may be included in the response, and your application should not treat this as an error. The set shown above is the minimum set.

A successful response is returned as a JSON object, similar to the following:


Calling a Google API

After your application obtains an access token, you can use the token to make calls to a Google API on behalf of a given user account or service account. To do this, include the access token in a request to the API by including either an access_token query parameter or an Authorization: Bearer HTTP header. When possible, the HTTP header is preferable, because query strings tend to be visible in server logs. In most cases you can use a client library to set up your calls to Google APIs (for example, when calling the Drive API).

You can try out all the Google APIs and view their scopes at the OAuth 2.0 Playground.


A call to the drive.files endpoint (the Drive API) using the Authorization: Bearer HTTP header might look like the following, though you'll need to specify your own access token:

GET /drive/v2/files HTTP/1.1
Authorization: Bearer 1/fFBGRNJru1FQd44AzqT3Zg

Here is a call to the same API for the authenticated user (me) using the access_token query string parameter:


You can try out with the curl command-line application. Here's an example using the HTTP header option (preferred):

curl -H "Authorization: Bearer 1/fFBGRNJru1FQd44AzqT3Zg"

Or, alternatively, the query string parameter option:


Using a refresh token

To obtain a new access token, send an HTTPS POST request to The request must include the following parameters:

Field Description
refresh_token The refresh token returned from the authorization code exchange.
client_id The client ID you obtained from the Google API Console.
client_secret The client secret you obtained from the API Console (not applicable for clients registered as Android, iOS or Chrome applications).
grant_type As defined in the OAuth 2.0 specification, this field must contain a value of refresh_token.

Such a request looks similar to the following:

POST /oauth2/v4/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

As long as the user has not revoked the access granted to your application, the response is formatted like the token response from the code exchange, and includes a new access token. A sample response from such a request is shown below:

  "access_token": "ya29.Ci8SAzMH13iQa1t1buFUtN_v8X5wirj-bEmUM4VaaHJwPrh4ZUF5SiBIqMlxOU_58g",
  "token_type": "Bearer",
  "expires_in": 3600,
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImRkMmFhMTNlNzkzZjU3OTU2ZmE1NDgxZTJmOTViZWZiMzA5ZTkyNTMifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXRfaGFzaCI6InJtUWZ0a082Q1dJWHFEbU9QdTNMQlEiLCJhdWQiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTAxNjk0ODQ0NzQzODYyNzYzMzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNDA3NDA4NzE4MTkyLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiZW1haWwiOiJiaWxsZDE2MDBAZ21haWwuY29tIiwiaWF0IjoxNDY3Mzk5ODk4LCJleHAiOjE0Njc0MDM0OTh9.ZtjcAx1AiGVeHP7hA3uPVNgYcskpXTfMa4Z3284DgC2pbv6Su53x1xTO_BDatSM_-qBg4x-tDsoU74c9YtpcLqnR4xNUyulFGths6NkXHXLJjuXIRivLVKuZSvkCaGJl-q6g6xMCt8mm5oRyVSBfEkvmfnsJ895awRCKR3NZo35gbCCDcGgZYX_4w2AwGBkh67REfy-XWwZT3DOLHtKh9dB_yypGdNDdNPONKk5jieAxh42jzosu9XOyZS1BJUZAu7GKsKULzWYO9-Ft6rE8QsNb0MxzpdGbb8cWzI54ER691dA4jwtMTHZ_ymTBF3fp7mSMpWHy1pYZZpRfBLPcJQ"

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.

Further Reading

The Internet-Draft Best Current Practice: OAuth 2.0 for Apps establishes many of the best practices documented here.