I was trying to find a way to validate tokens in my Android app, however I read somewhere here that "It's unusual for an Android app to verify or even sign a token." Why is it unusual? Does this mean that there is no way of verifying tokens in native apps?
firstly lets understand what makes a token usable as a stateless auth agent. basically JWT is just a json object which has 3 parts
header
payload
signature
Signature method is sha256(base64(header)+base64(payload)+"secret message").
"secret message" defines how strong the token is. server verifies the validity of the token which this secret key.
Now if you would like to verify the token on your client side, you definitely need this secret key. DOING THIS WILL COMPROMISE THE SECURITY :)
Hope I was able to shed some light on why we should not verify the token on client side. Let's leave the verification to server.
Related
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
As we know. the Android apk can be decompiled. Even if you're using ProGuard, anyone can see your server URLs. I have a basic authenticate scheme on my server where the client passes an AuthToken in the header of a request; if someone manages to steal that AuthToken then they can fool the server.
Which authentication system I should use to prevent this as I have to include something (Key | AuthToken ) in my Java code (app doesn't requires a login).
Here are my pointers on this subject.
APK reverse engineering is doable and your URL is definitely susceptible to attacks. This can be avoided by using token based authentication. Which you are already doing.
How do you think someone can steal auth token? only possibility is to do a network spoofing. This can be avoided using HTTPS.
Also, the token should not be stored anywhere on your device. It should be in memory and every time the user opens the app request for a new token. Since you have mentioned that the app does not need any login, you can provide a short lived auth token or expire the token at server end.
You can also read more on this topic here https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
We have a service where user can sign-up. This process is protected by reCAPTCHA to prevent automatized sign-ups. The problem is that on mobile devices reCAPTCHA is not a convenience. Therefore we decided that the sign-up API will accept also some special tokens instead of reCAPTCHA response.
Now the question is how to implement this token. Our first approach was to equip the mobile application with some constant secret that would be sent to the server as the token. But this secret can be revealed if a hacker redirects the request to his server (by updating DNS record of the API domain and installing his certificate as trusted to the mobile device).
Now our final approach is to compute the token as HMAC-SHA1 on username+secret (do we need a here secred - maybe just for making the input long enough?). The username will be taken from sign-up input. Then the server would authorize it by validating the hash. In his case it would be possible to do a replay attack but it is OK because duplicate username would be rejected.
Is this approach correct? Maybe there are other alternatives to captcha on mobile devices?
Also is it possible to get and reverse engineer the application from iOS (ipa file) considering it will be hosted in Appstore and to extract the key (and secret)?
In case of android this is possible - is there a way to prevent it?
You found the disadvantage: you still with a token which doesn't change for the same user. It's ok in your use case (register), but there could be another use cases where is not useful (for example a password recovery feature. In that case, a possible hacker might generate valid tokens for any user is your are asking for the username).
My solution would be:
Create an algorithm (on both mobile app and your backend) that takes a "public token" and creates a "secret token", which solves the captcha. It might be a simple SHA1 hash (I don't recommend), a combination between public token and a salt, the user id and public token, etc...
Create an endpoint on your API that generates public and secret tokens. Store secret token in your backend and return public token to the client (mobile app).
You app then should ask for the public token, generate the secret token and send it to the API. The API verifies that secret token is already stored in your database, and if it's the case then captcha is solved.
An improvement would be making stored secret tokens to expire after X seconds.
Hope it helps!
We decided to go with Hawk to not to send credentials over the wire. It will be used for iOS where it shouldn't be possible to reverse engineer the app and get the secret key. For Android we'll use some reCAPTCHA library for Android.
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.
I read almost everything I could find about C2DM but what I couldn't understand is the auth token which the server needs in order to send a message.
Do I need to pass the server the password of the user in order for him to get the token?
Or am I missing something?
I don't want to ask the user to enter their password (if it's needed than it's pretty easy to do a phising app).
If I do need to send a token is there a way to get it with the accountmanager api?
Thanks.
After some consideration, is it possible I got confused and the auth token is really my gmail account(the developer)?
Take a look at JumpNote example project: http://code.google.com/p/jumpnote/
It has both the client and server side code you can rummage through.
As for the auth token, JumpNote project has helper shell script to get one: http://code.google.com/p/jumpnote/source/browse/trunk/scripts/get_auth_token.sh
This script will ask you for your Google Account credentials, and will retrieve an auth token that you can use for, I don't know, some time.