Android: Get token of authenticated account - android

I have android app comunicating with api on remote server. I want to make user authentication via google account. I know there's many pages/questions about this topic, but I kind of couldn't figured out which method I need to use.
What I want is, when user registers with his google account, his account will be authenticated and then I want Google to generate some auth token, which is specific for the app and users account. This token should never change, because it should be used on api server to authenticate user.
Do I need to link my app somehow to Google AppEngine or is there any simple solution which I'm not seeing? Or is this method of authenticating completly wrong?

You might be a bit wrong. Cause No one (Not even the Google apps on android) ever get a non expiring token. You Need to save the refresh token and the current token. and after every hour you need to refresh the token using refresh token. And you are good to go (If I have understood your question :P). I would suggest if you already own a server better host the back-end there else GAE works just fine. I hope it helps :)

Related

Google signin in Android app to consume Cloud Endpoints backend

I am writing an Android app with a Google Cloud Endpoints backend, and I want to restrict my backend with a Google signin.
I have followed the Android instructions, and have successfully logged in. In other words, I have received a token, which I can then pass to the server and verify the user it stands for. Great.
However, I am missing the bigger picture here. Questions:
Am I supposed to be sending this token with each request back to the server, and repeat the process of verifying it in each request?
If yes, the token will expire at some point (1 hour I believe). I suppose the user does not have to login again, there should be away to avoid this, right?
Is a way to refresh the token (I think Google Signin is OAuth2)?
And most importantly, is all this the standard way someone uses Google signin to protect their backend? I was expecting this to be very straightforward process, since I am only using Google products. However, I am finding myself lost in pages and pages of documentation on Android and Cloud Enpoints with pieces of the puzzle.
Any help or insight is appreciated.
I have not used android authentication but google uses outh2 for all its authentication. Google SDKs may help you alleviate some of the pain of using oauth2. To answer your questions
Yes - You are in the world of token based authentication and you do send the token with every request.
Yes. token will expire after an hour. To get around this when you first do an oauth2 authentication, you also get a refresh token. When the token of the user expires you use the refresh token to get the new token. This refresh token can be stored on the client side. Client will find during one of its requests that that existing token is expired and would request for a new token using refresh token
Yes you use the google refresh token URL to use the refresh token and get the new token. I have given the important oauth URLs of google below.
This is indeed oauth2 process my friend.
since you are using cloud endpoint I believe that you would be making the authentication endpoints.
You generally make the following endpoints when doing oauth2 authentication using a service provider(google, facebook, github, etc):
https://webiste.com/auth/signin/{provider}
https://webiste.com/auth/callback/{provider}
https://webiste.com/auth/refresh/{provider}
Following are the google URLs for oauth2 that you would use:
oauth_url: 'https://accounts.google.com/o/oauth2/v2/auth', //start auth
token_url: 'https://accounts.google.com/o/oauth2/token', //get id_token, access_token, refresh_token token
refresh_token_url : 'https://www.googleapis.com/oauth2/v4/token',
token_info_url: 'https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=', //validate token
You would also want to go through google's oauth2 documentation at https://developers.google.com/identity/protocols/OAuth2.
I think you should Firebase UI Android Library for Authentication. It provides you with Google, Facebook, Email, Twitter and Github signin options and good part is that it can be done by writing only few lines of code.
For more information click here.
It's best practice to use 3ed party code to do this. It will take much less time, will have much less bugs and will be very easy to expand to other methods later.
I would recommend Firebase because it's very easy, free, works well and owned by Google.

How to carry identity/auth from Android app to server?

I started using firebase auth with google and while that works I'm unsure how I can transfer a user's identity to a server call. For example
User authenticates in my Android app. I know they are xyz#gmail.com
Now I need to make a call to the server (not firebase/app engine) and the server needs to know this is user xyz#gmail without reauthenticating. I thought I'd send the auth-token and then I could verify it on the server with same id/secret, but the auth-token that I get back from IdpResponse does not work.
Any ideas on the recommended solution for this situation? Thanks
This is well documented on firebase
https://firebase.google.com/docs/auth/admin/verify-id-tokens
Works beautifully. I'm still not sure why the auth token doesn't work with the google oauth client.

Android Authentication - What is the standard?

I am getting into Android development for the first time and am having a blast, of course. I do have a question, though, about the general approach to authentication (for dealing with a backend).
To begin, here is, in a nut shell, what I have worked out.
Using google's documentation (link), I authenticate the user using the google sign in api. I have put the logic mentioned in the reference in my app's main activity. After the onConnected method fires, I have a successfully connected GoogleApiClient.
With the now connected GoogleApiClient, I use a call to GoogleAuthUtil.getToken to get an oath2 token that I use to authenticate requests to my backend. Basically, any time I make an HTTP request to my backend, I include this token as a header. My backend reads this token and uses the Python API google provides for verifying this token. In the backend, I use the email that is embedded in the (now parsed) token to make sure the user to whom that oauth2 token was issued is, in fact, a user of my system.
Now, here are the questions. First, does this sound like a reasonable approach to authentication on the Android platform? What might I be missing? What could go wrong?
The second question is a bit more direct. When I get the oauth2 token from the client app, I store it and use the same token each time an HTTP request to a secured resource is made. Eventually, of course, the token will expire. From some limited testing using the Android emulator, it seems that if I shut down the application and restart it, I am getting the same, expired token back using the GoogleAuthUtil.getToken, rather than getting a fresh token with a new expiration in the future. In my tests, I have had to restart the emulator in order to get a token with a correct expiry. Am I mistaken here? Is there something special I need to do to tell the Google API to issue me a new token? Do I need to disconnect the GoogleApiClient and reconnect it? I hope to avoid doing this in order to limit the number of activities that need to carry the callbacks required to complete this process.
Any words of wisdom here will be greatly appreciated!
after you have got your token you can use Validate Token, and if it responses with an error: 'invalid_token', you can use GoogleAuth.clearToken(Context context, String token) to clear the token and get a new token with the method you are using to get auth token.

Authenticating with OAuth2 for an app *and* a website

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 using Google's OAuth2 stuff, since it provides a decent UI on Android.
Google states that "You can choose to use Google's authentication system as a way to outsource user authentication for your application. This can remove the need to create, maintain, and secure a username and password store." which is what I want to do. However when I go through all their examples and whatnot, I can only find stuff about having a website or an app authenticate a user against Google's services.
And indeed, when I go to register my app ("client") with Google's OAuth2 there are options for website clients and "installed" clients (i.e. a mobile app) but not both. I can create two separate clients but I read the OAuth2 draft and I think there will be a problem, which I will now explain.
Here's how I did envisage it working:
User asks MyApp to access his private data.
App uses Android's AccountManager class to request an access token for Google's APIs.
Android says to user "The app 'MyApp' wants access to your Basic Information on Google. Is this ok?"
User says yes.
AccountManager connects to Google's OAuth2 server using the credentials stored on the phone, and asks for an access token.
Access token (which follows the green lines) is returned.
AccountManager returns the access token to MyApp.
MyApp sends a request to MySite for the user's private data, including the access token.
MySite needs to verify the user, using the access token. It validates the token as described here, with Google - "Google, is this token valid?".
Now, what I want to happen is that Google says "Yes, whoever gave it to you is indeed that user.", but what I think will actually happen (based on the OAuth2 draft and Google's documentation) is that it will say "No way! That token is only valid for MyApp, and you're MySite. GTFO!".
So how should I do this? And PLEASE don't say "Use OpenID" or "Don't use OAuth2" or other similarly unhelpful answers. Oh and I would really like to keep using the nice AccountManager UI rather than crappy popup WebViews
Edit
Provisional answer (I will report back if it works!) from Nikolay is that it should actually work, and Google's servers won't care where the access token came from. Seems a bit insecure to me, but I will see if it works!
Update
I implemented this pattern with Facebook instead of Google and it totally works. The OAuth2 server doesn't care where the access token comes from. At least Facebook's doesn't, so I assume Google's doesn't either.
In light of that it is a very very bad idea to store access tokens! But we also don't want to have to hit Facebook/Google's servers to check authentication for every request since it will slow everything down. Probably the best thing is to add an additional authentication cookie for your site that you hand out when their access token is validated, but a simpler way is just to treat the access token like a password and store a hash of it. You don't need to salt it either since access tokens are really really long. So the steps above become something like:
9. MySite needs to verify the user, using the access token. First it checks its cache of hashed valid access tokens. If the hash of the token is found there it knows the user is authenticated. Otherwise it checks with Google as described here, with Google - "Google, is this token valid?".
10. If Google says the access token is invalid, we tell the user to GTFO. Otherwise Google says "Yes that is a valid user" and we then check our registered user database. If that Google username (or Facebook id if using Facebook) is not found we can create a new user. Then we cache the hashed value of the access token.
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> ...
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
it describes exactly what you want:
https://developers.google.com/identity/protocols/CrossClientAuth
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.
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.
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.

Android APP that consumes a webservice how to authenticate users

I'm developing an android app that consumes a webservice that I will develop too (I'm thinking in using a RESTFul webservice)..
and I want to secure the connection between the app and the server but I need to authenticate users too..
My problem is in the last part, to secure the connection I think the best way to do it is to use SSL (https), am I wrong?
I don't know what's "the best way" to authenticate users, to make sure that a user cannot consume the webservice as another user..
I have some ideas, like using a authenticate(login,pass) method on the webservice that returns a token.. And for any operation that requires authentication the user would need to pass that token as a parameter.. The thing is, is this a good way to do this? whats the most common technique used to auth users in a situation like this?
If a token based auth is a good idea how should I generate the token?
Sorry for this long text..
Any help will be usefull
Thanks
Make sure you understand a trendy standard like OAuth before you go down that path. Most OAuth flows are centered around a user logging in to your server through a web browser. This can lead to pretty bad user experience for a mobile app. The standard does allow for alternatives. Here's a decent introduction.
You could also use an existing identity provider like Google, Facebook, Twitter, etc. instead of implementing your own authN/authZ. On Android, you can ask for a Google auth token using the AccountManager. This usually works because the user needs to be logged in to their Google account to access the Android Market. Anyway, this will prompt the user to grant authorization to your app. You could then use the Google auth token to login your user to your service with your own token. The login would essentially be your server verifying the Google token is valid (by contacting Google's servers) and then issuing its own token to be used for calls to your web services. If you don't like Google, you could use the Facebook SDK, etc.
As for what to use for tokens... The OAuth spec has stuff on that as well. You could do something as simple as a random string or something as complex as encrypted SAML assertions.
You should implement a token based OAuth, which will require the users to log in once, and then permanently have access.
You can use Google App Engine which already provides user authentication services for you (your Android users most likely already have google accounts) But this is only one of many options.
You can also look into Amazon's Identity Access Management (IAM) which will allow you to manage the users who have access to your web service, and authorize them accordingly.
I think the best way to do it is to use SSL (https), am I wrong?
This only prevents certain types of malicious use, but not everything. There is still nothing to prevent people from accessing your database on the phone, and retrieving credentials that way.

Categories

Resources