Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 1 | page.title=Authorization |
Joe Fernandez | 33baa5a | 2013-11-14 11:41:19 -0800 | [diff] [blame] | 2 | page.tags=AccountManager,oauth2 |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 3 | @jd:body |
| 4 | |
| 5 | <div id="qv-wrapper"> |
| 6 | <div id="qv"> |
| 7 | <h2>In this document</h2> |
| 8 | <ol> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 9 | <li><a href="#choose">Choosing an Account</a></li> |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 10 | <li><a href="#obtain">Obtaining an Access Token</a></li> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 11 | <li><a href="#handle">Handling Exceptions</a></li> |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 12 | <li><a href="#use">Using the Access Token</a></li> |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 13 | </ol> |
| 14 | </div> |
| 15 | </div> |
| 16 | |
| 17 | <p> |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 18 | 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 Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 22 | requests or using a client library provided by the service provider. |
| 23 | </p> |
| 24 | |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 25 | <p>For implementation details, see the sample in <code><android-sdk>/extras/google-play-services/samples/auth</code>, |
Dirk Dougherty | d9065a5 | 2013-07-28 14:02:01 -0700 | [diff] [blame] | 26 | which shows you how to carry out these basic steps for obtaining an access token.</p> |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 27 | |
| 28 | <h2 id="choose">Choosing an Account</h2> |
| 29 | <p> |
| 30 | Google Play services leverage existing accounts on an Android-powered device |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 31 | to gain authorization to the services that you want to use. To obtain an access token, |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 32 | 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 Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 35 | <a href="{@docRoot}reference/com/google/android/gms/common/AccountPicker.html">{@code |
| 36 | AccountPicker}</a> |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 37 | 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 Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 43 | in an array. When obtaining an access token, only the email address of the account is |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 44 | needed, so that is what the array stores: |
| 45 | </p> |
| 46 | |
| 47 | <pre> |
| 48 | private 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 < names.length; i++) { |
| 54 | names[i] = accounts[i].name; |
| 55 | } |
| 56 | return names; |
| 57 | } |
| 58 | </pre> |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 59 | <h2 id="obtain">Obtaining an Access Token</h2> |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 60 | <p> |
Robert Ly | 4efe071 | 2013-01-18 13:33:25 -0800 | [diff] [blame] | 61 | 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 | |
| 66 | There are two general |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 67 | ways to get a token:</p> |
| 68 | |
| 69 | <ul> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 70 | <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 Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 73 | display a dialog to the user to interactively handle authorization errors.</li> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 74 | <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 Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 76 | 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 Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 78 | </ul> |
| 79 | |
| 80 | <h3>Using getToken()</h3> |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 81 | 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 Ly | 4efe071 | 2013-01-18 13:33:25 -0800 | [diff] [blame] | 82 | |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 83 | <pre> |
| 84 | HelloActivity mActivity; |
| 85 | String mEmail; |
| 86 | String mScope; |
| 87 | String token; |
| 88 | |
| 89 | ... |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 90 | try { |
| 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 Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 98 | is in an {@link android.os.AsyncTask}. |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 99 | The sample in the Google Play services SDK shows you how to wrap this call in an AsyncTask. |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 100 | If authorization is successful, the token is returned. If not, the exceptions described in |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 101 | <a href="#handle">Handling Exceptions</a> |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 102 | are thrown that you can catch and handle appropriately. |
| 103 | </p> |
| 104 | |
| 105 | <h3>Using getTokenWithNotification()</h3> |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 106 | <p>If you are obtaining access tokens in a background service or sync adapter, there |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 107 | 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 Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 110 | that you can use:</p> |
| 111 | <ul> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 112 | <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 Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 114 | For background services. Displays a notification to the user when authorization errors occur.</li> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 115 | <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 Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 118 | when authorization errors occur. If a user clicks the notification and then authorizes the |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 119 | app to access the account, the intent is broadcasted. When using this method: |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 120 | <ul> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 121 | <li>Create a {@link android.content.BroadcastReceiver} that registers the intent and handles |
| 122 | it 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 |
| 127 | android.content.Intent#toUri toUri(Intent.URI_INTENT_SCHEME)} and |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 128 | {@link android.content.Intent#parseUri parseUri(intentUri, Intent.URI_INTENT_SCHEME)} methods.</li> |
| 129 | </ul> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 130 | <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>: |
| 132 | This method is for use in sync adapters. It displays a notification to the user when |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 133 | errors occur. If a user clicks the notification and then authorizes the |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 134 | app to access the account, the sync adapter retries syncing with the information |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 135 | contained in the <code>syncBundle</code> parameter.</li> |
| 136 | </ul> |
| 137 | |
| 138 | <p>See the sample in <code><android-sdk>/extras/google-play-services/samples/auth</code> for implementation details.</p> |
| 139 | |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 140 | |
| 141 | |
| 142 | |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 143 | <h2 id="handle">Handling Exceptions</h2> |
| 144 | <p> |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 145 | When requesting an access token with |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 146 | <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 Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 148 | the following exceptions can be thrown: |
| 149 | </p> |
| 150 | <ul> |
| 151 | <li> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 152 | <a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html" |
| 153 | >{@code UserRecoverableAuthException}</a>: |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 154 | 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 Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 163 | <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 Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 167 | 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 Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 174 | <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code |
| 175 | GoogleAuthException}</a>: |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 176 | This exception is thrown when the authorization fails, such as when an invalid scope is |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 177 | specified or if the email address used for authorization is actually not on the user's |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 178 | device. |
| 179 | </li> |
| 180 | <li> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 181 | <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 Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 186 | 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 Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 192 | <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code |
| 193 | GoogleAuthUtil}</a> class. |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 194 | </p> |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 195 | |
| 196 | |
| 197 | |
| 198 | |
Robert Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 199 | <h2 id="use">Using the Access Token</h2> |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 200 | <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> |
| 208 | URL url = new URL("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" |
| 209 | + token); |
| 210 | HttpURLConnection con = (HttpURLConnection) url.openConnection(); |
| 211 | int serverCode = con.getResponseCode(); |
| 212 | //successful query |
| 213 | if (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 Ly | 292bed2 | 2012-12-14 12:22:04 -0800 | [diff] [blame] | 234 | signifies an authorization error (401). This could mean the access token |
Robert Ly | 6519ca0 | 2012-11-14 13:26:28 -0800 | [diff] [blame] | 235 | being used is invalid for the service's scope or the token may have expired. If this is the |
Scott Main | e36276a | 2012-12-02 16:07:30 -0800 | [diff] [blame] | 236 | case, obtain a new token using <a |
| 237 | href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)" |
| 238 | >{@code GoogleAuthUtil.getToken()}</a>. |
Joe Fernandez | 33baa5a | 2013-11-14 11:41:19 -0800 | [diff] [blame] | 239 | </p> |