blob: dd99b453b0fdc9889ec3a01051d272791ff0efb3 [file] [log] [blame]
<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://&lt;extension-id&gt;.chromiumapp.org/&lt;anything-here&gt;</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': '&lt;url-to-do-auth&gt;', 'interactive': true},
function(redirect_url) { /* Extract token from redirect_url */ });
</pre>
<p>
The &lt;url-to-do-auth&gt; 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&amp;<br>redirect_uri=https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb&amp;response_type=token&amp;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=&lt;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>