summaryrefslogtreecommitdiffstats
path: root/docs/html/google/play-services/auth.jd
blob: 8e111315a2c4c73974f97e5913788e1f23363119 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
page.title=Authorization
@jd:body

<div id="qv-wrapper">
  <div id="qv">    
    <h2>In this document</h2>
    <ol>
    <li><a href="#choose">Choosing an Account</a></li>
    <li><a href="#obtain">Obtaining an Access Token</a></li>
    <li><a href="#handle">Handling Exceptions</a></li>
    <li><a href="#use">Using the Access Token</a></li>
    </ol>
  </div>
</div>

<p>
    Google Play services offers a standard authorization flow for all Google APIs and
    all components of Google Play services. In addition, you can leverage the authorization
    portion of the Google Play services SDK to gain authorization to services that are not yet supported 
    in the Google Play services platform by using the access token to manually make API
    requests or using a client library provided by the service provider.
</p>

<p>For implementation details, see the sample in <code>&lt;android-sdk&gt;/extras/google-play-services/samples/auth</code>,
which shows you how to carry out these basic steps for obtaining an acesss token.</p>

<h2 id="choose">Choosing an Account</h2>
<p>
    Google Play services leverage existing accounts on an Android-powered device
    to gain authorization to the services that you want to use. To obtain an access token,
    a valid Google account is required and it must exist on the device. You can ask your users which
    account they want to use by enumerating the Google accounts on the device or using the
    built-in 
<a href="{@docRoot}reference/com/google/android/gms/common/AccountPicker.html">{@code
AccountPicker}</a>
    class to display a standard account picker view. You'll need the
    {@link android.Manifest.permission#GET_ACCOUNTS}
    permission set in your manifest file for both methods.
</p>
<p>
    For example, here's how to gather all of the Google accounts on a device and return them
    in an array. When obtaining an access token, only the email address of the account is 
    needed, so that is what the array stores:
</p>

<pre>
private String[] getAccountNames() {
    mAccountManager = AccountManager.get(this);
    Account[] accounts = mAccountManager.getAccountsByType(
            GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
    String[] names = new String[accounts.length];
    for (int i = 0; i &lt; names.length; i++) {
        names[i] = accounts[i].name;
    }
    return names;
}
</pre>
<h2 id="obtain">Obtaining an Access Token</h2>
<p>
  With an email address and the service scope you can now obtain an access token.
</p>
<p class="note"><strong>Note:</strong> Specify <code>"oauth2:<em>scope</em>"</code> for a single scope or
  <code>"oauth2:<em>scope1</em> <em>scope2</em> <em>scope3</em>"</code> for multiple scopes.</p>

There are two general
  ways to get a token:</p>

    <ul>
      <li>Call one of the two overloaded <a
      href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
      >{@code GoogleAuthUtil.getToken()}</a> methods in a foreground activity where you can
        display a dialog to the user to interactively handle authorization errors.</li>
      <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)"
      >{@code getTokenWithNotification()}</a>
        methods if you are trying to gain authorization in a background service or sync adapter so that a
        notification is displayed if an error occurs.</a></li>
    </ul>

    <h3>Using getToken()</h3>
    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}:

<pre>
HelloActivity mActivity;
String mEmail;
String mScope;
String token;

...
try {
    token = GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
} catch {
    ...
}
</pre>

<p>Call this method off of the main UI thread since it executes network transactions. An easy way to do this
  is in an {@link android.os.AsyncTask}.
  The sample in the Google Play services SDK shows you how to wrap this call in an AsyncTask.
  If authorization is successful, the token is returned. If not, the exceptions described in
<a href="#handle">Handling Exceptions</a>
  are thrown that you can catch and handle appropriately.
</p>

  <h3>Using getTokenWithNotification()</h3>
  <p>If you are obtaining access tokens in a background service or sync adapter, there
  are three overloaded
  <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
      >{@code getTokenWithNotification()}</a> methods
  that you can use:</p>
  <ul>
    <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)"
    >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras)}</a>:
    For background services. Displays a notification to the user when authorization errors occur.</li>
    <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)"
    >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, Intent callback)}</a>:
    This method is for use in background services. It displays a notification to the user
    when authorization errors occur. If a user clicks the notification and then authorizes the
    app to access the account, the intent is broadcasted. When using this method:
    <ul>
     <li>Create a {@link android.content.BroadcastReceiver} that registers the intent and handles
it appropriately</li>
     <li>In the app's manifest file, set the <a
     href="{@docRoot}guide/topics/manifest/receiver-element.html#exported"><code>android:exported</code></a>
     attribute to <code>true</code> for the broadcast receiver</li>
     <li>Ensure that the intent is serializable using the {@link
android.content.Intent#toUri toUri(Intent.URI_INTENT_SCHEME)} and
    {@link android.content.Intent#parseUri parseUri(intentUri, Intent.URI_INTENT_SCHEME)} methods.</li>
   </ul>
    <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)"
    >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, String authority, Bundle syncBundle)}</a>:
This method is for use in sync adapters. It displays a notification to the user when
errors occur. If a user clicks the notification and then authorizes the
app to access the account, the sync adapter retries syncing with the information
    contained in the <code>syncBundle</code> parameter.</li>
  </ul>
  
   <p>See the sample in <code>&lt;android-sdk&gt;/extras/google-play-services/samples/auth</code> for implementation details.</p>




<h2 id="handle">Handling Exceptions</h2>
<p>
    When requesting an access token with
    <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
    >{@code GoogleAuthUtil.getToken()}</a>,
    the following exceptions can be thrown:
</p>
<ul>
    <li>
<a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
>{@code UserRecoverableAuthException}</a>: 
        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.
        This exception class contains a {@link android.app.Activity#getIntent getIntent()} 
        method that you can call to obtain an intent that you can use with
{@link android.app.Activity#startActivityForResult startActivityForResult()} 
        to obtain the user's resolution. You will need to handle the
{@link android.app.Activity#onActivityResult onActivityResult()} 
        callback when this activity returns to take action based on the user's actions.
  </li>
  <li>
<a href="{@docRoot}reference/com/google/android/gms/auth/GooglePlayServicesAvailabilityException.html"
>{@code GooglePlayServicesAvailabilityException}</a>: 
        This exception is a special case of <a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
        >{@code UserRecoverableAuthException}</a>
        and occurs when the actual Google Play services APK is not installed or unavailable.
        This exception provides additional client support to
        handle and fix this issue by providing an error code that describes the exact cause of the problem.
        This exception also contains an intent that you can obtain and use to start
        an activity to resolve the issue.
    </li>
    <li>
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code
GoogleAuthException}</a>:
        This exception is thrown when the authorization fails, such as when an invalid scope is 
        specified or if the email address used for authorization is actually not on the user's 
        device.
    </li>
    <li>
<a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableNotifiedException.html"
>{@code UserRecoverableNotifiedException}</a>:
        This exception is thrown when the authorization fails using one of the
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
      >{@code getTokenWithNotification()}</a> methods and if the error
        is recoverable with a user action.
    </li>
</ul>
<p>
    For more information on how to handle these exceptions and code snippets, see the reference 
    documentation for the 
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code
GoogleAuthUtil}</a> class.
</p>




<h2 id="use">Using the Access Token</h2>
<p>
    Once you have successfully obtained a token, you can use it to access Google services.
    Many Google services provide client libraries, so it is recommended that you use these when 
    possible, but you can make raw HTTP requests as well with the token. The following example 
    shows you how to do this and handle HTTP error and success responses accordingly:
</p>

<pre>
URL url = new URL("https://www.googleapis.com/oauth2/v1/userinfo?access_token="
        + token);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
int serverCode = con.getResponseCode();
//successful query
if (serverCode == 200) {
    InputStream is = con.getInputStream();
    String name = getFirstName(readResponse(is));
    mActivity.show("Hello " + name + "!");
    is.close();
    return;
//bad token, invalidate and get a new one
} else if (serverCode == 401) {
    GoogleAuthUtil.invalidateToken(mActivity, token);
    onError("Server auth error, please try again.", null);
    Log.e(TAG, "Server auth error: " + readResponse(con.getErrorStream()));
    return;
//unknown error, do something else
} else {
    Log.e("Server returned the following error code: " + serverCode, null);
    return;
}
</pre>

<p>
    Notice that you must manually invalidate the token if the response from the server
    signifies an authorization error (401). This could mean the access token
    being used is invalid for the service's scope or the token may have expired. If this is the 
    case, obtain a new token using <a
href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
>{@code GoogleAuthUtil.getToken()}</a>.
</p>