I\'m developing a website that is primarily accessed via an app, and I want to use OAuth2 for user registration and authentication. Since it is an Android app I will start u
I just posted an answer to a similar StackOverflow question.
Google calls this Hybrid Apps and explains how an "Android app obtains offline access for Web back-end".
The gist of it is that you'll have to pass a massaged scope
string into GoogleAuthUtil.getToken
in order to get it to return an Authorization Code (not an OAuth2 Token). That Authorization Code can be passed from your mobile app to your server and be exchanged for an OAuth2 Token and Refresh Token, according to this schematic.
The scope
parameter needs to look something like this:
oauth2:server:client_id:<your_server_client_it>:api_scope:<scope_url_1> <scope_url_2> ...
When we had a need to do something similar on a non-google OAuth Server, we kept the tokens in a DB on the website. The app would then use web services to request the token when needed to request data.
The user could do the OAuth registration on either the web or app. They shared the same application token, so they could share the same access token. After the registration we would store the access and refresh tokens in the DB for use from whichever app needed it.
it describes exactly what you want: https://developers.google.com/identity/protocols/CrossClientAuth
At least with Google, the access token eventually expires. This is why the android AccountManager
has the invalidateAuthToken
method--the cached access token has expired, and you need to tell the AccountManager
to stop giving you the old one and instead get a new one. This makes it somewhat safer to cache the token, as the token itself doesn't give you eternal access as that user. Instead, when valid, it merely says "at some point in the recent past, this token was acquired by a trusted source."
Here are a couple of things I've found helpful when working with tokens. The first is Google's tokeninfo endpoint. The token itself is just base64-encoded JSON. This means it isn't encrypted, so you need to be sure to be using HTTPS for communication. However, it also means that you can examine the token and have a better idea of what's going on.
https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=
If your token was "abcdef", you would navigate to:
https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=abcdef
and Google would unpack the token for you. It is a simple JSON object that includes an "expires_in" field telling you the number of seconds for which the token is still valid. At 6:03 in the video below you can see the unpacked token:
https://developers.google.com/events/io/sessions/383266187
That video includes a thorough overview of OAuth2 and is well worth watching in its entirety if you're going to be dealing with OAuth and tokens. The speaker also discusses other forms of Oauth2 tokens, that are not access tokens, that do not expire.
Another useful resource is the OAuth Playground. This lets you do basic things like request scopes, make up requests, and get back tokens. This link seems to work sporadically, and on Chrome I had to install the Oauth Playground app:
https://developers.google.com/oauthplayground/
And here is a tutorial by Tim Bray, the speaker in the video, explaining how to use access tokens to communicate to a server from an Android app. This was useful to me because I began to understand how the different things in the Google API Console work together:
http://android-developers.blogspot.in/2013/01/verifying-back-end-calls-from-android.html
With regards to the actual answer to your question, I would say you never need to cache the access token on the server. As explained in the Verifying Back End Calls from Android link above, verifying a token is almost always a fast static call, meaning there's no reason to cache the tokens:
The libraries can cache the Google certs and only refresh them when required, so the verification is (almost always) a fast static call.
Finally, you can indeed use the AccountManager
to get access tokens. However, Google now instead encourages the use of the GoogleAuthUtil
class in the Play Services library instead:
In a nutshell what's the difference from using OAuth2 request getAuthToken and getToken
Here note the comment by Tim Bray, the same guy yet again from the above links, saying that they are putting their efforts into the GoogleAuthUtil
route. Note, however, that this means you would be limited to Google authentication. I believe that the AccountManager
could be used to get, for example, a Facebook token instead--not the case with GoogleAuthUtil
.
You probably need OpenID Connect, which uses OAuth tokens for authentication. As for AccountManager
, the current OAuth support is a bit hacky, the new Google Play Services, set to be released 'soon' should hopefully make this better. See here for a demo.
You can use the access token retrieved by the mobile application anywhere else. Drive SDK has a nice and simple intro that goes through the flow on https://developers.google.com/drive/quickstart-android