blob: 7acaf1cd6834532271ff19375b4c7b5c19107ebe [file] [log] [blame]
Robert Ly292bed22012-12-14 12:22:04 -08001page.title=Authorization
Scott Main6afeb0e2013-04-16 21:05:51 -07002page.tags="AccountManager","oauth2"
Robert Ly6519ca02012-11-14 13:26:28 -08003@jd:body
4
5<div id="qv-wrapper">
6 <div id="qv">
7 <h2>In this document</h2>
8 <ol>
Scott Maine36276a2012-12-02 16:07:30 -08009 <li><a href="#choose">Choosing an Account</a></li>
Robert Ly292bed22012-12-14 12:22:04 -080010 <li><a href="#obtain">Obtaining an Access Token</a></li>
Scott Maine36276a2012-12-02 16:07:30 -080011 <li><a href="#handle">Handling Exceptions</a></li>
Robert Ly292bed22012-12-14 12:22:04 -080012 <li><a href="#use">Using the Access Token</a></li>
Robert Ly6519ca02012-11-14 13:26:28 -080013 </ol>
14 </div>
15</div>
16
17<p>
Robert Ly292bed22012-12-14 12:22:04 -080018 Google Play services offers a standard authorization flow for all Google APIs and
19 all components of Google Play services. In addition, you can leverage the authorization
20 portion of the Google Play services SDK to gain authorization to services that are not yet supported
21 in the Google Play services platform by using the access token to manually make API
Robert Ly6519ca02012-11-14 13:26:28 -080022 requests or using a client library provided by the service provider.
23</p>
24
Robert Ly292bed22012-12-14 12:22:04 -080025<p>For implementation details, see the sample in <code>&lt;android-sdk&gt;/extras/google-play-services/samples/auth</code>,
Dirk Doughertyd9065a52013-07-28 14:02:01 -070026which shows you how to carry out these basic steps for obtaining an access token.</p>
Robert Ly6519ca02012-11-14 13:26:28 -080027
28<h2 id="choose">Choosing an Account</h2>
29<p>
30 Google Play services leverage existing accounts on an Android-powered device
Robert Ly292bed22012-12-14 12:22:04 -080031 to gain authorization to the services that you want to use. To obtain an access token,
Robert Ly6519ca02012-11-14 13:26:28 -080032 a valid Google account is required and it must exist on the device. You can ask your users which
33 account they want to use by enumerating the Google accounts on the device or using the
34 built-in
Scott Maine36276a2012-12-02 16:07:30 -080035<a href="{@docRoot}reference/com/google/android/gms/common/AccountPicker.html">{@code
36AccountPicker}</a>
Robert Ly6519ca02012-11-14 13:26:28 -080037 class to display a standard account picker view. You'll need the
38 {@link android.Manifest.permission#GET_ACCOUNTS}
39 permission set in your manifest file for both methods.
40</p>
41<p>
42 For example, here's how to gather all of the Google accounts on a device and return them
Robert Ly292bed22012-12-14 12:22:04 -080043 in an array. When obtaining an access token, only the email address of the account is
Robert Ly6519ca02012-11-14 13:26:28 -080044 needed, so that is what the array stores:
45</p>
46
47<pre>
48private String[] getAccountNames() {
49 mAccountManager = AccountManager.get(this);
50 Account[] accounts = mAccountManager.getAccountsByType(
51 GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
52 String[] names = new String[accounts.length];
53 for (int i = 0; i &lt; names.length; i++) {
54 names[i] = accounts[i].name;
55 }
56 return names;
57}
58</pre>
Robert Ly292bed22012-12-14 12:22:04 -080059<h2 id="obtain">Obtaining an Access Token</h2>
Robert Ly6519ca02012-11-14 13:26:28 -080060<p>
Robert Ly4efe0712013-01-18 13:33:25 -080061 With an email address and the service scope you can now obtain an access token.
62</p>
63<p class="note"><strong>Note:</strong> Specify <code>"oauth2:<em>scope</em>"</code> for a single scope or
64 <code>"oauth2:<em>scope1</em> <em>scope2</em> <em>scope3</em>"</code> for multiple scopes.</p>
65
66There are two general
Robert Ly6519ca02012-11-14 13:26:28 -080067 ways to get a token:</p>
68
69 <ul>
Scott Maine36276a2012-12-02 16:07:30 -080070 <li>Call one of the two overloaded <a
71 href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
72 >{@code GoogleAuthUtil.getToken()}</a> methods in a foreground activity where you can
Robert Ly292bed22012-12-14 12:22:04 -080073 display a dialog to the user to interactively handle authorization errors.</li>
Scott Maine36276a2012-12-02 16:07:30 -080074 <li>Call one of the three <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
75 >{@code getTokenWithNotification()}</a>
Robert Ly292bed22012-12-14 12:22:04 -080076 methods if you are trying to gain authorization in a background service or sync adapter so that a
77 notification is displayed if an error occurs.</a></li>
Robert Ly6519ca02012-11-14 13:26:28 -080078 </ul>
79
80 <h3>Using getToken()</h3>
Robert Ly292bed22012-12-14 12:22:04 -080081 The following code snippet obtains an access token with an email address, the scope that you want to use for the service, and a {@link android.content.Context}:
Robert Ly4efe0712013-01-18 13:33:25 -080082
Robert Ly6519ca02012-11-14 13:26:28 -080083<pre>
84HelloActivity mActivity;
85String mEmail;
86String mScope;
87String token;
88
89...
Robert Ly6519ca02012-11-14 13:26:28 -080090try {
91 token = GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
92} catch {
93 ...
94}
95</pre>
96
97<p>Call this method off of the main UI thread since it executes network transactions. An easy way to do this
Scott Maine36276a2012-12-02 16:07:30 -080098 is in an {@link android.os.AsyncTask}.
Robert Ly6519ca02012-11-14 13:26:28 -080099 The sample in the Google Play services SDK shows you how to wrap this call in an AsyncTask.
Robert Ly292bed22012-12-14 12:22:04 -0800100 If authorization is successful, the token is returned. If not, the exceptions described in
Scott Maine36276a2012-12-02 16:07:30 -0800101<a href="#handle">Handling Exceptions</a>
Robert Ly6519ca02012-11-14 13:26:28 -0800102 are thrown that you can catch and handle appropriately.
103</p>
104
105 <h3>Using getTokenWithNotification()</h3>
Robert Ly292bed22012-12-14 12:22:04 -0800106 <p>If you are obtaining access tokens in a background service or sync adapter, there
Scott Maine36276a2012-12-02 16:07:30 -0800107 are three overloaded
108 <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
109 >{@code getTokenWithNotification()}</a> methods
Robert Ly6519ca02012-11-14 13:26:28 -0800110 that you can use:</p>
111 <ul>
Scott Maine36276a2012-12-02 16:07:30 -0800112 <li><a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
113 >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras)}</a>:
Robert Ly292bed22012-12-14 12:22:04 -0800114 For background services. Displays a notification to the user when authorization errors occur.</li>
Scott Maine36276a2012-12-02 16:07:30 -0800115 <li><a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle, android.content.Intent)"
116 >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, Intent callback)}</a>:
117 This method is for use in background services. It displays a notification to the user
Robert Ly292bed22012-12-14 12:22:04 -0800118 when authorization errors occur. If a user clicks the notification and then authorizes the
Scott Maine36276a2012-12-02 16:07:30 -0800119 app to access the account, the intent is broadcasted. When using this method:
Robert Ly6519ca02012-11-14 13:26:28 -0800120 <ul>
Scott Maine36276a2012-12-02 16:07:30 -0800121 <li>Create a {@link android.content.BroadcastReceiver} that registers the intent and handles
122it appropriately</li>
123 <li>In the app's manifest file, set the <a
124 href="{@docRoot}guide/topics/manifest/receiver-element.html#exported"><code>android:exported</code></a>
125 attribute to <code>true</code> for the broadcast receiver</li>
126 <li>Ensure that the intent is serializable using the {@link
127android.content.Intent#toUri toUri(Intent.URI_INTENT_SCHEME)} and
Robert Ly6519ca02012-11-14 13:26:28 -0800128 {@link android.content.Intent#parseUri parseUri(intentUri, Intent.URI_INTENT_SCHEME)} methods.</li>
129 </ul>
Scott Maine36276a2012-12-02 16:07:30 -0800130 <li><a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle, java.lang.String, android.os.Bundle)"
131 >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, String authority, Bundle syncBundle)}</a>:
132This method is for use in sync adapters. It displays a notification to the user when
Robert Ly292bed22012-12-14 12:22:04 -0800133errors occur. If a user clicks the notification and then authorizes the
Scott Maine36276a2012-12-02 16:07:30 -0800134app to access the account, the sync adapter retries syncing with the information
Robert Ly6519ca02012-11-14 13:26:28 -0800135 contained in the <code>syncBundle</code> parameter.</li>
136 </ul>
137
138 <p>See the sample in <code>&lt;android-sdk&gt;/extras/google-play-services/samples/auth</code> for implementation details.</p>
139
Scott Maine36276a2012-12-02 16:07:30 -0800140
141
142
Robert Ly6519ca02012-11-14 13:26:28 -0800143<h2 id="handle">Handling Exceptions</h2>
144<p>
Robert Ly292bed22012-12-14 12:22:04 -0800145 When requesting an access token with
Scott Maine36276a2012-12-02 16:07:30 -0800146 <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
147 >{@code GoogleAuthUtil.getToken()}</a>,
Robert Ly6519ca02012-11-14 13:26:28 -0800148 the following exceptions can be thrown:
149</p>
150<ul>
151 <li>
Scott Maine36276a2012-12-02 16:07:30 -0800152<a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
153>{@code UserRecoverableAuthException}</a>:
Robert Ly6519ca02012-11-14 13:26:28 -0800154 This exception is thrown when an error occurs that users can resolve, such as not yet granting access to their accounts or if they changed their password.
155 This exception class contains a {@link android.app.Activity#getIntent getIntent()}
156 method that you can call to obtain an intent that you can use with
157{@link android.app.Activity#startActivityForResult startActivityForResult()}
158 to obtain the user's resolution. You will need to handle the
159{@link android.app.Activity#onActivityResult onActivityResult()}
160 callback when this activity returns to take action based on the user's actions.
161 </li>
162 <li>
Scott Maine36276a2012-12-02 16:07:30 -0800163<a href="{@docRoot}reference/com/google/android/gms/auth/GooglePlayServicesAvailabilityException.html"
164>{@code GooglePlayServicesAvailabilityException}</a>:
165 This exception is a special case of <a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
166 >{@code UserRecoverableAuthException}</a>
Robert Ly6519ca02012-11-14 13:26:28 -0800167 and occurs when the actual Google Play services APK is not installed or unavailable.
168 This exception provides additional client support to
169 handle and fix this issue by providing an error code that describes the exact cause of the problem.
170 This exception also contains an intent that you can obtain and use to start
171 an activity to resolve the issue.
172 </li>
173 <li>
Scott Maine36276a2012-12-02 16:07:30 -0800174<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code
175GoogleAuthException}</a>:
Robert Ly6519ca02012-11-14 13:26:28 -0800176 This exception is thrown when the authorization fails, such as when an invalid scope is
Robert Ly292bed22012-12-14 12:22:04 -0800177 specified or if the email address used for authorization is actually not on the user's
Robert Ly6519ca02012-11-14 13:26:28 -0800178 device.
179 </li>
180 <li>
Scott Maine36276a2012-12-02 16:07:30 -0800181<a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableNotifiedException.html"
182>{@code UserRecoverableNotifiedException}</a>:
183 This exception is thrown when the authorization fails using one of the
184<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
185 >{@code getTokenWithNotification()}</a> methods and if the error
Robert Ly6519ca02012-11-14 13:26:28 -0800186 is recoverable with a user action.
187 </li>
188</ul>
189<p>
190 For more information on how to handle these exceptions and code snippets, see the reference
191 documentation for the
Scott Maine36276a2012-12-02 16:07:30 -0800192<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code
193GoogleAuthUtil}</a> class.
Robert Ly6519ca02012-11-14 13:26:28 -0800194</p>
Scott Maine36276a2012-12-02 16:07:30 -0800195
196
197
198
Robert Ly292bed22012-12-14 12:22:04 -0800199<h2 id="use">Using the Access Token</h2>
Robert Ly6519ca02012-11-14 13:26:28 -0800200<p>
201 Once you have successfully obtained a token, you can use it to access Google services.
202 Many Google services provide client libraries, so it is recommended that you use these when
203 possible, but you can make raw HTTP requests as well with the token. The following example
204 shows you how to do this and handle HTTP error and success responses accordingly:
205</p>
206
207<pre>
208URL url = new URL("https://www.googleapis.com/oauth2/v1/userinfo?access_token="
209 + token);
210HttpURLConnection con = (HttpURLConnection) url.openConnection();
211int serverCode = con.getResponseCode();
212//successful query
213if (serverCode == 200) {
214 InputStream is = con.getInputStream();
215 String name = getFirstName(readResponse(is));
216 mActivity.show("Hello " + name + "!");
217 is.close();
218 return;
219//bad token, invalidate and get a new one
220} else if (serverCode == 401) {
221 GoogleAuthUtil.invalidateToken(mActivity, token);
222 onError("Server auth error, please try again.", null);
223 Log.e(TAG, "Server auth error: " + readResponse(con.getErrorStream()));
224 return;
225//unknown error, do something else
226} else {
227 Log.e("Server returned the following error code: " + serverCode, null);
228 return;
229}
230</pre>
231
232<p>
233 Notice that you must manually invalidate the token if the response from the server
Robert Ly292bed22012-12-14 12:22:04 -0800234 signifies an authorization error (401). This could mean the access token
Robert Ly6519ca02012-11-14 13:26:28 -0800235 being used is invalid for the service's scope or the token may have expired. If this is the
Scott Maine36276a2012-12-02 16:07:30 -0800236 case, obtain a new token using <a
237href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
238>{@code GoogleAuthUtil.getToken()}</a>.
Robert Ly6519ca02012-11-14 13:26:28 -0800239</p>