Proper way to authenticate with a backend server - android

According to the doc, in order to authenticate with a backend server I have to :
send the user's ID token to my server using HTTPS.
verify the integrity of the ID token and retrieve the user's ID from the sub claim of the ID token.
This work quite well, but how to do if I have to authenticate all the request to the server ?
Should I store the idToken (on a private sharred preferences) and verify it each time server side ? Since the idToken have a validity date, the client must be able to regenerate it when it has expired.
Or on the first connection, should I return a single id (without validity date) to the user which will allow him to communicate with the server (seems less secure) ?

The token should be verify with every request to the server it's like a key for each request. This key is not valid for a long time period so you have normally a refresh token if you want the "session" to be persistent. If you don't have it you will need to authenticate again every time the validity period of the token is expired.
So yes you should store the token in the client side. The best practice is to have a really short validity period to be sure that if the token is compromise the attacker will have a short time to do malicious thing.

I foud a technical answer (#EmCode's answer is correct) in the doc of the silentSignIn() method. (Here is a link).
The GoogleSignInResult will possibly contain an ID token which may be used to authenticate and identify sessions that you establish with your application servers. If you use the ID token expiry time to determine your session lifetime, you should retrieve a refreshed ID token, by calling silentSignIn prior to each API call to your application server.

See if this makes sense:
This work quite well, but how to do if I have to authenticate all the request to the server ?
I think the purpose of google sign-in is to authenticate users by their google credentials. It is not really for authenticating all your client requests against your own server. What will happens between your server and google should be only user token validation. Once the token is validated fine, the subsequent C/S data exchange can use authentication of your choice, and no need to bother google each time or care about the token validity.
If you use the ID token expiry time to determine your session lifetime, you should retrieve a refreshed ID token, by calling
silentSignIn prior to each API call to your application server.
Yes, if sessions are used your application and you want the token to define validity, then you need to bother Google all the time.

The Proper way to authenticate with a backend server is retrofit use this lib this is very fast to fetch data or upload data on beckend server.

Related

Handle token authentication on the client side

Given an API which uses token authentication (e.g., JWT), how would a client store and cache the token? To remedy the effect of stolen tokens, tokens usually expire after a certain amount of time. However, almost all applications require only to login once. How do they realize authentication? Do their tokens have no validity period or do the apps automatically apply for a new token?
You can store your token in an Account Manager on Android. Regarding token validity all apps have this tokens expire from within hours to days depending on how fast you want to change them.
There is no specific way to handle expired tokens you will have to write your own custom logic for this. Generally what a lot of apps follow is if the user's token has expired they use an api that takes the old token and if the token is not a very old like if it expired within 1 - 2 days they give back a new token but if in any case the token is historic they will logout the user and ask him to again login by providing password and username via your basic OAuth mechanism.

Authentication : Facebook user access token validation on server side?

A lot of questions here are talking about validation process of Facebook access token on the server side. I am bit confused how is still secure?
My client and server flows are:
User Continue with Facebook using Mobile SDK on the client side.
Facebook returns User access token to the client side.
Server endpoints receive user access token (via POST method) and validate the access_token using Graph API.
In case of authenticated user return the JWT authorization token in response
In the meantime (within an hour), If hackers find out the endpoint and pass the new access_token to the hacked endpoint.
What will happen if 5th point gets executed? It's difficult to hack the POST parameters but it might be possible after decompiling the app and see the classes file (At least for android apk). In this case, Server will not recognize the forged request and will always return the JWT Authorization token to make further calls.
The validity of Facebook access_token is 60 days. Do I need to provide an extra layer of security at the time of validation endpoint to make sure that the request is only coming from the application?
Is facebook user access_token always changing whenever a user is requesting to sign in?
Any kind of help would be appreciable. Thanks
Solution:
Generated access_token will always belongs to an App. To verify it pass the access_token and app_tokenin:
https://graph.facebook.com/debug_token?
access_token=ACCESS_TOKEN
&app_token=APP_TOKEN

Android Authenticator STORE A CRYPTOGRAPHICALLY SECURE TOKEN

I am authenticating using spongeycastle PKCS10CertificationRequest CSR to a RESTful Certificate Authority.
I'm considering using Android Authenticator.
According to: https://stuff.mit.edu/afs/sipb/project/android/docs/training/id-auth/custom_auth.html#Security
It's important to understand that AccountManager is not an encryption
service or a keychain. It stores account credentials just as you pass
them, in plain text. On most devices, this isn't a particular concern,
because it stores them in a database that is only accessible to root.
But on a rooted device, the credentials would be readable by anyone
with adb access to the device.
With this in mind, you shouldn't pass the user's actual password to
AccountManager.addAccountExplicitly(). Instead, you should STORE A
CRYPTOGRAPHICALLY SECURE TOKEN that would be of limited use to an
attacker.
My questions:
I'm not sure what is meant by STORE A CRYPTOGRAPHICALLY SECURE TOKEN in this context.
What does that token look like (its type?) in Android Java?
And where to store it? in the KeyChain??
Is that token used in any other context other than the pw in addAccountExplicitly()?
If your device has rich input capabilities (so user can input username\password) you may want to consider using something like JWT auth. In this case your app never keeps an actual user password, but sends it to the server only once per authentication session and gets back a JWT (JSON web token). This is a token with some information (for example, with a link to user resource - id or uuid) and TTL parameter securely signed with a secret key. This secret key lives on the server only so nobody outside of your server can generate a valid token.
So after authentication request you save JWT localy and use it in the "Authorization" header or as a request field (the first option is better because request body can appears in logs) with every API query. You should renew this token before it expires and if it was expired - then ask user to enter his credentials again. From the server side you get a request, validate a token (is it signed with the server secret key and isn't it expired?) and in case of valid token serve a request. You don't even need to keep tokens on server but you might want to do it if you want more control over authentication - for example, if you want to revoke tokens from outside of application workflow.
There is a list with a lot of libraries for JWT for different languages on the JWT site. For example, for using with Elixir\Phoenix you might want to use Guardian. From Android part in a simple case you don't even need to have a special tools for working with JWT - just put token as a plain text string to the "Authorization" header and send request to the server. But in case you want to get (decode) information your server has put to the token from the app side or check token expiration time - then you'll need to use one of the libraries presented on jwt site.

Oauth2.0 flow for Google App Engine and Android App

I see some similar questions related to this question but those ones are too old to be considered, so I will ask again here.
I have an Android App that needs to authenticate to a web service to exchange data that will be stored on Google App Engine. For that, I would like to use OAuth2.0 to provide an authentication mechanism between my App and the web service as shown here: https://developers.google.com/identity/protocols/OAuth2WebServer?hl=en and here https://developers.google.com/identity/protocols/CrossClientAuth
I'm already doing a validation of the token on the web service side as shown on the documentation. The only part that I don't have clear is what to do on the GAE web service and Android after a refresh token is being obtained on Android and validated on the web service.
The questions are:
Must I exchange this token all the time for every communication
between the app and the web service? is it secure?
What is the best way to keep the communications going forward?
After researching about this, this authentication flow I'm using:
Sign in on the app as shown here: https://developers.google.com/identity/sign-in/android/sign-in
After Sign in, obtain a token.
Send the token over HTTPS to backend server
Validate the token on backend server with GoogleIdTokenVerifier verifier (you can also call the tokeninfo endpoint) as shown here: https://developers.google.com/identity/sign-in/android/backend-auth
When you receive the Token on your backend server you should:
After you receive the ID token by HTTPS POST, you must verify the integrity of the token. To verify that the token is valid, ensure that the following criteria are satisfied:
The ID token is a JWT that is properly signed with an appropriate Google public key (available in JWK or PEM format).
The value of aud in the ID token is equal to one of your app's client IDs. This check is necessary to prevent ID tokens issued to a malicious app being used to access data about the same user on your app's backend server.
The value of iss in the ID token is equal to accounts.google.com or https://accounts.google.com.
The expiry time (exp) of the ID token has not passed.
If your authentication request specified a hosted domain, the ID token has a hd claim that matches your Google Apps hosted domain.
User authenticated. Token must be sent over on the request header for every communication with the backend server, then the backend server needs to verify it everytime.

How to put user authentication into a mobile application

I'm interested in the best way to do user auth in a mobile app. At the moment the set up is quite simple. I'm storing the username and password on the app and sending it to the api each time I need to run a restricted query.
This I feel is probably the wrong way to go about this.
Would a better way to be to send the username and password when the user logs in and then store that user's id? The problem with this is that then the api accepts a user id and not a username and password. A user id will be much easier to "guess" at and malicious persons would be able to submit a req to the api with randomly selected user id's performing actions under their account. I have an api key. Is this secure enough?
The issue is that I want to start integrating twitter and facebook oauth into the app. I haven't read much about it, but I think you get a "token". How would this work with the set up that you're suggesting? Would there be benefit to creating a token in my own database of users and using the token (whether it be mine, facebook's or twitter's) as the authorisation? Or would it make sense to keep each service separate and deal with them separately?
Thank you.
The correct way would be to generate auth token on the server when user logs and send this token in login reply. Then this token is used in subsequent requests.
This means that server must keep track of auth tokens it generates. You can also track token creation times and make tokens expire after some time.
Token must be a sufficiently long random string, so that it can not be easily guessed. How to do this was answered before: How to generate a random alpha-numeric string?
Personally I prefer the UUID approach.
Update:
This problem was already solved in web browsers, via cookies and sessions. You can reuse this mechanism in your Android requests (though some REST purists disprove this approach):
Enable sessions on server.
When user logs into a server add some data to session, for instance time of login:
request.getSession().setAttribute("timeOfLogin", System.currentTimeMillis());
Since sessions are enabled, you also need to enable support for cookies in your HttpClient requests: Using Cookies across Activities when using HttpClient
Every time a request is made, server should check if session contains timeOfLogin attribute. Otherwise it should return HTTP 401 reply.
When user logs out, call server logout url and clear the cookies on client.

Categories

Resources