Token based authentication for log-in in Android Application - android

The application I am developing is a credit scoring application. This software should prevent unauthorized access. In order to implement this, I've used user and password-based authentication with two roles available - standard user and administrator.
This was implemented entirely in Python by using SQLAlchemy for interacting with the database, and Android for the user interface. For authentication, I am calling User Management System to get a token:
Request Body:
{
"username": "credit_scoring",
"password": "132465"
}
Response Body:
{
"apiData": {
"navigationList": [],
"userId": "credit_scoring",
"userName": "credit_scoring",
"email": "credit_scoring#erainfotechbd.com",
"cellNo": "01255",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiJjcyIsIm5iZiI6MTY1OTUyNzcxOCwiZXhwIjoxNjYwMTMyNTE4LCJpYXQiOjE2NTk1Mjc3MThasdasd9.4lkEv-TpwIyYcldXfKucy3ynewhbuUFgjtdnKm7ymjE",
"page": 0,
"pageSize": 0,
"searchString": null,
"skip": 0
},
"message": "Record has been saved.",
"isExecute": true,
"totalRecord": 0
}
For security purposes, I have inserted some letters in the token. So currently, the token in this data is invalid.
Now, I want to save this token in the Android application and if the token is expired, then the user should be logged out from the application. How can I do that? Any help will be highly appreciated.

First of all, you must answer a question what does it mean for you, that the user is logged out from a mobile app? This might mean:
deleting the access token from the app's memory
deleting any data about the user from memory (e.g., username, profile picture, etc.)
maybe deleting the entries mentioned above from persistent storage, if these were not only kept in the memory, etc.
Once you have the logout logic implemented, you need a trigger for the logout itself. The best solution (in my opinion) will be to listen to 401 responses from your APIs and call logout when you get such a response. Another way is to check the expiration time of the access token (the exp claim contains expiration) and call logout when the token is expired. You can make such checks e.g., every time you make a call to the API, or set up an interval function (as you know the expiration time upfront you can set the logout event to trigger at the given time). Even if you decide to go with the second option, you will still need a mechanism to catch 401 responses from the API — responses from the backend should be your source of truth, not anything you calculate on the frontend (e.g., there might be clock skews present on the device, or the token might get revoked, etc.)

Related

What to do if token expired

I have communicate with API using retrofit. When the user is log in, I save account to database and when the user go to app next time, I get data from database (so I skipped login screen). Problem is when user's token expires.
How to handle the situation?
in login fragment
PSEUDOCODE
user = ... //get user from database
if(user != null) {
startActivityAccountActivity();
}
//onButtonClick
emailLogin();
Don't go to your "logged in" activity just because you have a token saved, because as you have correctly noticed, it may be invalid. Try authenticating with the API when you get the token, and only go to the "logged in" activity if it indeed worked. Otherwise proceed as if there was no token saved (and remove the expired one from the database).
You should also note that the token may expire when the user is in the "logged in" activity. For example, the user logged in, used the app and then went to another app from the recents screen. A week later he/she returns to your app with the "logged in" activity open, but in the mean time the token has expired and nothing will work. So you should also check if the token still works there, maybe in the onStart() of the activity.
As indramurari said, you can also handle it on the backend if you control it. But keep in mind that it doesn't solve your inherent problem of handling expired tokens, a refresh token may also expire and you are back to square one. If you make refresh tokens not expire you can just make the login tokens not expire. (This paragraph would be a comment on his answer, but I don't have enough reputation.)
It depends on your back end security level. You have two options to handle this situation.
Build some mechanism on back end side so that your server will send some refresh-token along with the user's token at the time of login to Android device. Whenever user's token get expired then request from Android device to your server to obtain new user's token by sending old user's token along with refresh-token. And you can use that new user's token for future. Repeat this whenever user's token get expired.
Note - refresh-token is for validating if it is valid resource who is requesting for a user's token.
You can delete the user account from database and tell user to Re-Login.

How to make sure bots won't create many users on my app?

I have an android app that communicates with a server. The app when run for the first time will send a post request to /user/register_device and then the server will create a new user with random id and random key and returns the response
{
"status": "success",
"data": {
"uid": "sfasdfas2487329rhsdifasor092u403p8412jelfjsakl;dfajs09204u12341",
"ukey": "fs04932u401923u4jweofksa;ldfajs9-24-341243fasdfasdffdsafasfasfsafrweqrqgq4234fdsfasdfa34123"
}
}
But now if an attacker makes a script that just send post requests to /user/register_device in a loop, he can create many users in the server. This will soon fill up the table with invalid users. So how to stop this?
Should I restrict the number of requests coming from an IP? Or should i add a secret_key into the android app and make app send this key too when registering_device? Are there any other methods to stop this?
Restricting by IP address may affect the functionality since many organisations use NAT scheme to hide internal IP addresses.
my suggestions
1. Use Captcha
2. Double opt-in. When someone signs up through a subscribe form an email is immediately sent to the address they provided.
3. create a unique key per user based on MAC address if the key appears again you should ignore it.
4. Put a checkbox "I'm human"
http://uxmovement.com/forms/captchas-vs-spambots-why-the-slider-captcha-wins/
5. Use SMS for verication

ParseUser.getCurrentUser() confusion

I'm using Parse as the backend.
To check if the user is logged in I use ParseUser.getCurrentUser(). What I don't understand is, if the user changes his password from somewhere else (another device, the web-client), will this ParseUser return with some kind of error?
I don't think it does a check on the server, so I think it just returns the last saved user. This mean that I can continue to use this user (with an old password) or will I get a "wrong credential" response on the first request to the servers?
If I don't get it, will I at least get it when setting an ACL with parseObject.setACL(new ParseACL(ParseUser.getCurrentUser()));?
Try same action on yahoo in 2 open browsers of different types and see what you get?
Each client's been handed a token value by the respective servers and until the token expire will not be prompt for a new logon.
Well IMO Parse work very similar except the lease on Parse token never expire.
Response to the original parse logon contain the token value which the SDK may retain. Details are in the docs section on Rest api / user logon...
So, if a diff client change password but the token lease over on some other client never expire, the other client stays logged in.

Why I am getting exception after trying to access Box?

Some days ago I asked how to retain Box tokens (Load, save and use of authentication data in Box Android API). Now, when user wants to access his Box account I use this code to configure BoxAndroidClient:
client = new BoxAndroidClient(C, S);
client.authenticate(loadAuth()); //loadAuth() returns BoxAndroidOAuthData object
For short period of time after obtaining authentication data it works good. But after an hour or so I get an AuthFatalFailureException:
07-06 17:21:01.841: W/System.err(3647): com.box.boxjavalibv2.exceptions.AuthFatalFailureException
07-06 17:21:01.841: W/System.err(3647): at com.box.boxjavalibv2.authorization.OAuthDataController.doRefresh(OAuthDataController.java:275)
07-06 17:21:01.841: W/System.err(3647): at com.box.boxjavalibv2.authorization.OAuthDataController.refresh(OAuthDataController.java:191)
07-06 17:21:01.841: W/System.err(3647): at org.redscorpio.cloudtest.network.Box$2$1.run(Box.java:71)
Line 71 is
client.getOAuthDataController().refresh();
but it happens every time I need to access Box:
client.getFoldersManager().getFolderItems(current.getId(), LIST_REQUEST()).getEntries();
client.getFoldersManager().getFolder("0", DEFAULT_REQUEST);
I suspect that my token is invalidated at some point, but I don't know why it can't be renewed and why it happens after such a short period of time.
What I can do to prevent this?
I am not exactly sure what's going on. The sdk does auto refresh the token. However every time the token is refreshed, you actually will get a new refresh token and new access token, the old refresh token will not be valid any more. So basically the easiest way probably is update your stored OAuth token object every time your api call succeeds.
In the meantime, can you double check(maybe add some loggings) whether the stored refresh token and access token are the latest ones?
You can logcat out the access token in the code of token refresh:
com.box.boxjavalibv2.authorization.OAuthDataController class, doRefresh() method.
and in the place where api call is made: com.box.boxjavalibv2.authorization.OAuthAuthorization class, getAuthString() method.
When a user logs in and accepts your app's grant, you exchange the authorization_code for an access_token and a refresh_token (response shown below). The reason your token invalidates is that the access_token expires in one hour. You can exchange the refresh_token, which is valid for 14 days, for another one-hour access token. This is why you'll want the app to store both the access_token and the refresh_token, ensuring that a user will only need to re-authenticate if they return to the app after more than 14 days.
Using the refresh_token for another access_token will always return one more of each (refresh + access).
{
"access_token": "T9cE5asGnuyYCCqIZFoWjFHvNbvVqHjl",
"expires_in": 3600,
"token_type": "bearer",
"refresh_token": "J7rxTiWOHMoSC1isKZKBZWizoRXjkQzig5C6jFgCVJ9bUnsUfGMinKBDLZWP9BgR"
}

Stuck on scrumptious tutorial, how to get an "active access token"?

The title pretty much sums it up, i am trying to test my Open Graph Actions in the Graph API Explorer but when i POST to /me/mynamespace:myaction, i get this error (Using the access token the Graph API Explorer generated for me, i asked for publish_actions only)
{
"error": {
"message": "(#15) This method must be called with an app access_token.",
"type": "OAuthException",
"code": 15
}
}
Ive done my homework and searched about it, to find a proper access-token to solve this problem goes by the APPID|APP_SECRET format but using that i get
{
"error": {
"message": "An active access token must be used to query information about the current user.",
"type": "OAuthException",
"code": 2500
}
}
Any ideas on how to solve this?
To give out more context the graph actions were created for an android facebook app.
You can't post to /me without a user access token from a user who's logged into your app, 'me' is a placeholder for 'current user'.
It sounds like two things have happened here:
You've configured the Open Graph action to require the App Access Token to post (which is a configuration option on the action
When you came across that error, you tried to use the App Access Token but didnt' change /me/mynamespace:myaction to /<USER ID>/mynamespace:myaction
Some notes:
Never put the app access token into your client code; it can be used to modify app settings. If you really need actions to only be postable via the app access token, you'll need to implement a server-side component to your app which makes the requests with the app access token
You probably need to change the open graph action settings for your action so it can be posted with a user access token
Your method of sending APP_ID|SECRET as an app access token is wrong. To get an app access token, you need to request it via this endpoint:
https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID
&client_secret=YOUR_APP_SECRET&grant_type=client_credentials
See here for more details

Categories

Resources