| <h1>Identify User</h1> |
| |
| <p> |
| Web authentication protocols utilize HTTP features, |
| but Chrome Apps run inside the app container; |
| they don’t load over HTTP and can’t perform redirects or set cookies. |
| </p> |
| |
| <p> |
| Use the <a href="identity.html">Chrome Identity API</a> |
| to authenticate users: |
| the <code>getAuthToken</code> for users logged into their Google Account and |
| the <code>launchWebAuthFlow</code> for users logged into a non-Google account. |
| If your app uses its own server to authenticate users, you will need to use the latter. |
| </p> |
| |
| <p class="note"> |
| <b>API Samples: </b> |
| Want to play with the code? |
| Check out the |
| <a href="https://github.com/GoogleChrome/chrome-app-samples#authentication-and-user-identification">identity samples</a>. |
| </p> |
| |
| <h2 id="how">How it works</h2> |
| |
| <p> |
| Chrome Apps users have a Google account associated with their |
| profile. Apps can get OAuth2 tokens for these users using |
| the <code>getAuthToken</code> API. |
| </p> |
| |
| <p> |
| Apps that want to perform authentication with non-Google identity |
| providers must call <code>launchWebAuthFlow</code>. This method uses a |
| browser pop-up to show the provider pages and captures redirects to |
| the specific URL patterns. The redirect URLs are passed to the app |
| and the app extracts the token from the URL. |
| </p> |
| |
| <h2 id="google">Google account authentication</h2> |
| |
| <p> |
| Here are the five steps you need to complete: |
| </p> |
| |
| <ol> |
| <li>Add permissions to your manifest and upload your app.</li> |
| <li>Copy key in the installed <code>manifest.json</code> to |
| your source manifest, so that your application ID will stay |
| constant during development.</li> |
| <li>Get an OAuth2 client ID for your Chrome App.</li> |
| <li>Update your manifest to include the client ID and scopes.</li> |
| <li>Get the authentication token.</li> |
| </ol> |
| |
| <h3 id="add_permissions">Add permissions and upload app</h3> |
| |
| <p> |
| You need to make sure the identity permission is in your manifest. |
| You can then upload your app to the apps and extensions management |
| page (see <a href="publish_app.html">Publish</a>). |
| </p> |
| |
| <pre data-filename="manifest.json"> |
| "permissions": [ |
| "identity" |
| ] |
| </pre> |
| |
| <h3 id="copy_key">Copy key to your manifest</h3> |
| |
| <p> |
| When you register your application in the Google OAuth console, you'll |
| provide your application's ID, which will be checked during token |
| requests. Therefore it's important to have a consistent application ID |
| during development. |
| </p> |
| |
| <p> |
| To keep your application ID constant, you need to copy the key in the |
| installed |
| <code>manifest.json</code> to your source manifest. |
| It's not the most graceful task, but here's how it goes: |
| </p> |
| |
| <ol> |
| <li>Go to your <a href="http://www.chromium.org/user-experience/user-data-directory">user data |
| directory</a>. Example on MacOs: |
| <code>~/Library/Application\ Support/Google/Chrome/Default/Extensions</code></li> |
| <li>List the installed apps and extensions and match your app ID on the apps and extensions |
| management page to the same ID here.</li> |
| <li>Go to the installed app directory (this will be a version within the app ID). |
| Open the installed <code>manifest.json</code> (pico is a quick way to open the file).</li> |
| <li>Copy the "key" in the installed <code>manifest.json</code> and paste it into your app's |
| source manifest file.</li> |
| </ol> |
| |
| <h3 id="client_id">Get your OAuth2 client ID</h3> |
| |
| <p> |
| You need to register your app |
| in the Google APIs Console |
| to get the client ID: |
| </p> |
| |
| <ol> |
| <li>Login to the <a href="https://code.google.com/apis/console/">Google APIs Console</a> |
| using the same Google account used to upload your app to the Chrome Web Store. </li> |
| <li>Create a new project by expanding the drop-down menu in the top-left |
| corner and selecting the <strong>Create...</strong> menu item. </li> |
| <li> Once created and named, go to the "Services" navigation menu item and |
| turn on any Google services your app needs. </li> |
| <li> Go to the "API Access" navigation menu item and click on the |
| <strong>Create an OAuth 2.0 client ID...</strong> blue button. </li> |
| <li> Enter the requested branding information, |
| select the <strong>Installed application</strong> type. </li> |
| <li> Select <strong>Chrome Application</strong> and enter your application ID |
| (same ID displayed in the apps and extensions management page). </li> |
| </ol> |
| |
| <p class="warning"> |
| <strong>Warning: </strong> |
| If the app ID here does not match your app ID, |
| an error will occur when your app calls <a href="#token">getAuthToken()</a>. |
| </p> |
| |
| <h3 id="update_manifest">Update your manifest with OAuth2 client ID and scopes</h3> |
| |
| <p> |
| You need to update your manifest to include |
| the client ID and scopes. |
| Here's the sample "oauth2" for the |
| <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/gdrive">gdrive sample</a>: |
| </p> |
| |
| <pre data-filename="manifest.json"> |
| "oauth2": { |
| "client_id": "665859454684.apps.googleusercontent.com", |
| "scopes": [ |
| "https://www.googleapis.com/auth/drive" |
| ] |
| } |
| </pre> |
| |
| <h3 id="token">Get access tokens</h3> |
| |
| <p> |
| You are now ready to get the auth token by calling |
| $ref:identity.getAuthToken. |
| </p> |
| |
| <pre> |
| chrome.identity.getAuthToken({ 'interactive': true }, function(token) { |
| // Use the token. |
| }); |
| </pre> |
| |
| <h4 id="getAuthToken-prompts">User interaction</h4> |
| |
| <p> |
| When calling <code>getAuthToken</code>, you can pass a flag |
| (<code>'interactive': true</code> in the example above) indicating |
| whether you want the API to be called in interactive mode or silent |
| mode. If you invoke the API in interactive mode, the user is shown |
| a sign in and/or approval UI when necessary, as shown in the |
| screenshot below: |
| </p> |
| <img src="{{static}}/images/identity-api-ui.png" |
| width="853" |
| height="514" |
| alt="screenshot showing UI when an app uses the Identity API |
| to authenticate a Google account"> |
| |
| <p> |
| If you invoke the API in silent mode, the API will only return a token |
| if it's possible to produce one without showing any UI. This is |
| useful in cases when an app is doing the flow at app startup, for |
| example, or in general in cases where there is no user gesture |
| involved. |
| </p> |
| |
| <p> |
| The best practice we suggest is to use silent mode when there is no |
| user gesture involved and use interactive mode if there is a user |
| gesture (for example, the user clicked the Sign In button in your |
| app). Note that we do not enforce any gesture requirement. |
| </p> |
| |
| <h4 id="getAuthToken-caching">Caching</h4> |
| |
| <p> |
| Chrome has an in-memory cache of access tokens, so you can call |
| <code>getAuthToken</code> any time you need to use a token. Token |
| expiration is handled automatically by the cache. |
| </p> |
| |
| <p> |
| You can see the current state of the token cache |
| on <code>chrome://identity-internals</code>. |
| </p> |
| |
| <p> |
| There are some cases, such as when the user changes their password, |
| when non-expired access tokens will stop working. API calls using the |
| token will start returning with an HTTP status code 401. If you detect |
| that this has happened, you can remove the invalid token from Chrome's |
| cache by calling $ref:identity.removeCachedAuthToken. |
| </p> |
| |
| <p> |
| Example of <code>removeCachedAuthToken</code> usage: |
| </p> |
| |
| <pre> |
| // callback = function (error, httpStatus, responseText); |
| function authenticatedXhr(method, url, callback) { |
| var retry = true; |
| function getTokenAndXhr() { |
| chrome.identity.getAuthToken({/* details */}, |
| function (access_token) { |
| if (chrome.runtime.lastError) { |
| callback(chrome.runtime.lastError); |
| return; |
| } |
| |
| var xhr = new XMLHttpRequest(); |
| xhr.open(method, url); |
| xhr.setRequestHeader('Authorization', |
| 'Bearer ' + access_token); |
| |
| xhr.onload = function () { |
| if (this.status === 401 && retry) { |
| // This status may indicate that the cached |
| // access token was invalid. Retry once with |
| // a fresh token. |
| retry = false; |
| chrome.identity.removeCachedAuthToken( |
| { 'token': access_token }, |
| getTokenAndXhr); |
| return; |
| } |
| |
| callback(null, this.status, this.responseText); |
| } |
| }); |
| } |
| } |
| </pre> |
| |
| <h2 id="non">Non-Google account authentication</h2> |
| |
| <p> |
| Here are the three steps you need to complete: |
| </p> |
| |
| <ol> |
| <li>Register with the provider.</li> |
| <li>Add permissions for provider resources that your app will access.</li> |
| <li>Get the authentication token.</li> |
| </ol> |
| |
| <h3 id="register_provider">Register with the provider</h3> |
| |
| <p> |
| You need to register an OAuth2 client ID with the provider |
| and configure the client ID as a website. |
| For the redirect URI to be entered during registration, |
| use the URL of the form: |
| <code>https://<extension-id>.chromiumapp.org/<anything-here></code> |
| </p> |
| |
| <p> |
| For example, if you app ID |
| is <code>abcdefghijklmnopqrstuvwxyzabcdef</code> and you want |
| <code>provider_cb</code> to be the path, to distinguish it with |
| redirect URIs from other providers, you should use: |
| <code>https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb</code> |
| </p> |
| |
| <h3 id="permissions_provider">Add permissions for provider</h3> |
| |
| <p> |
| To make cross-origin XHRs to Google API endpoints, |
| you need to whitelist those patterns in the permissions: |
| </p> |
| |
| <pre data-filename="manifest.json"> |
| "permissions": [ |
| ... |
| "https://docs.google.com/feeds/", |
| "https://docs.googleusercontent.com/", |
| "https://www.website-of-provider-with-user-photos.com/photos/" |
| ] |
| </pre> |
| |
| <h3 id="token2">Get the token</h3> |
| |
| <p> |
| To get the token: |
| </p> |
| |
| <pre> |
| chrome.identity.launchWebAuthFlow( |
| {'url': '<url-to-do-auth>', 'interactive': true}, |
| function(redirect_url) { /* Extract token from redirect_url */ }); |
| </pre> |
| |
| <p> |
| The <url-to-do-auth> is whatever the URL is to do auth to the provider from a website. |
| For example, let us say that you are performing OAuth2 flow with a provider |
| and have registered your app with client id 123456789012345 and |
| you want access to user’s photos on the provider’s website: |
| <code>https://www.website-of-provider-with-user-photos.com/dialog/oauth?client_id=123456789012345&<br>redirect_uri=https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb&response_type=token&scope=user_photos</code> |
| </p> |
| |
| <p> |
| The provider will perform authentication and if appropriate, |
| will show login and/or approval UI to the user. |
| It will then redirect to |
| <code>https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb#authToken=<auth-token></code> |
| </p> |
| |
| <p> |
| Chrome will capture that and invoke the callback |
| of the app with the full redirect URL. |
| The app should extract the token out of the URL. |
| </p> |
| |
| <h3 id="launchWebAuthFlow-interactive">Interactive versus silent mode</h3> |
| |
| <p> |
| When calling <code>launchWebAuthFlow</code>, |
| you can pass a flag (<code>'interactive': true</code> in the example above) |
| indicating whether you want the API to be called |
| in interactive mode or not (aka silent mode). |
| If you invoke the API in interactive mode, |
| the user is shown UI, if necessary, |
| to get the token (signin UI and/or approval UI; |
| or for that matter any provider specific UI). |
| </p> |
| |
| <p> |
| If you invoke the API in silent mode, |
| the API will only return a token if the provider is able |
| to provide a token without showing any UI. |
| This is useful in cases when an app is doing the flow at app startup, for example, |
| or in general in cases where there is no user gesture involved. |
| </p> |
| |
| <p> |
| The best practice we suggest is to use silent mode |
| when there is no user gesture involved and use interactive mode |
| if there is a user gesture (for example, the user clicked the Sign In button in your app). |
| Note that we do not enforce gesture requirement. |
| </p> |
| |
| <p class="backtotop"><a href="#top">Back to top</a></p> |