Parse anonymous User ID doesn't persist on Android - android

I'm using anonymous users with parse but user ID keeps changing every time the app is restarted. I can create a serious of records, tied to a user and see them in backend / the app itself. Then kill the app, restart it and see a new user in Parse backend. Obviously, all records are no longer displayed because this is a "new user".
How can I make anonymous user id persist?

Turns out, if you're using Parse SDK and their anonymous users, you need to check if user is logged in and then run anonymous user initialization only in that case. Otherwise, each time the app is restarted, a new anonymous user is created. Makes sense but wasn't in their docs.

When you 'create' a new user, i think that you are getting an implied 'logon' of that new user.
Note that the response to the logon includes a session token ( no expiration on token ).
Using 'sharedPreferences' or some other android persistence technique, when you restart the app you can just retrieve the token from your persistence layer and - at least in REST API - just include that token in your headers along with AppId, and REST key and you will get that users data.
If you are using the SDK and not rest api, there may be some other way to get back to a reference for the user.

Related

Check user auth on every Activity

Is it appropriate to check user auth to server api in every activity (i assume using base activity on resume)? It is to prevent user login on multiple device with same account. Or is there better approach for this?
There is several approach to handle this.
Push notification - When same user login in another device then you need to send push notification to first login device. When first login device get notification then you can put your logic there.
Put Logout status on every api - You need to check logout status code in every api response. When you get logout status code then you can put your logic there.
Note: For second approach you need to make one generic api calling class. So, You don't need to put this status code in every api calling code.
So I'm assuming that every successful sign-in then the server gives you back a unique auth-token which should invalidate any previously assigned token.
My approach is usually just to allow the user to continue using the app with whatever cached data that's already there until I hit a scenario that needs to do an API call. And if I get an error code like HTTP 401 or 403 because the auth token was invalidated then should send me back to the sign-in screen.
Doing an explicit API call in onResume() seems wasteful and is basically client-side polling I would only do this if it was a very strict requirement to keep the auth information fresh because the information on screen is sensitive.

Realm - Does the .currentUser() deliver the current logged in on the mobile device or ist there another meaning to it?

I have checked the class SyncUser and the definition for the method currentUser() is: Returns the current user that is logged in and still valid.
What I want to know is, what exactly is delivered, when this method is executed? How reliable is the delivered value and what is the limitation regarding the definition of "current user".
Thanks for any information!
SyncUser.currentUser() is just a convenience method for retrieving a single SyncUser that have logged in on that particular device using either SyncUser.login() or SyncUser.loginAsync(). It only works if a single user is logged in, otherwise, you need to use SyncUser.allUsers().
This is commonly needed when the app is restarted. You can then check if the SyncUser already exists and thus there is no need for them to log in again. This can be useful in the case when the device is offline and logging in is not possible.
The SyncUser is represented by what is called an access token, which has a default lifetime of 10 years, so valid in this context just means "Access token granted by the Server that has not expired yet".
Of course, that information cannot be fully validated on the client, e.g if the Server was restored from a backup losing information about a particular token, then the Client might think the token is valid while the server will reject it. In that case, you will receive a callback on the SyncConfiguration.Builder.errorHandler(..) with an event you can react to and log the user in again.
You can see an example of this in practice in this example here: https://github.com/realm/realm-java/tree/master/examples/objectServerExample

Best method for running a "common" REST call before any other REST call

I have a REST API secured with JWT. The client is an Android app and a web app. Android app gets a new token when a user login, after that it works with that token. However the token will expire in 60 minutes, so I have to refresh it. I know there are 3 approaches for this.
issue a fresh token in every request
issue a fresh token when the current one is close to expire. e.g. 10
min
let client app request a new token when it needs it using a "refresh
service" of your api.
Please consider the following...
I am not happy about the first suggestion above
I did try the third suggestion. However in my android app I got like 60 REST calls. Then what I should be doing is with every REST call (ex: getUsers()), I first have to check whether the token is about to expire and if yes, get a new token from REST API (That means I have to run another REST call to the refresh() method in API). After this check and getting the new token I can execute the getUsers() method. The problem here is that every REST call should run inside the onResponse() method of my refresh() method (I am using Retrofit) and that is simply not possible as I have to then duplicate the same method for 60 times with 60 names. I am sure the same issue will arise with the web app as well.
Due to the above reasons I am considering the 2nd suggestions in my first list, renewing the token at the server it self. If the token is "valid" and if it is "about to expire" I will refresh it from server and will send to app as a header.
I need to know whether that method is an industry practicing method and whather it is the best choice. If not, how I can proceed with the 3rd suggestion in my first list.
I have recently implemented the similar setup with JWT in one of my Android apps. I don't know if my suggestion will help you, but it might give you an insight on how others are doing it.
Option 1: This is very much redundant, and it violates the sole purpose of using JWT in the first place. If I get a new JWT on every request, I can use that for further requests, thus practically have a token with no expiration.
Option 2: This requires server side extra operation, plus this is not feasible. How do you plan to detect which tokens are already distributed and "about to expire" so that you can renew them? Tons of users will have tons of tokens and if you plan to save JWT in database, then it would get too messy.
Option 3: This method is too redudndant and requires client side operation on checking whether token is about to expire and calling refresh service based on that. I always prefer lesser operation to do more work.
What I did, is that, I used two tokens for the system. One as a Refresh Token (token used to request JWT refresh) and one as JWT (for every request validation).
With successful login, received a refresh token and saved it locally in app (SharedPref). This token is also preserved in database too. Next, requested and validated JWT with that with that refresh token. From now onwards, every request contains this JWT in header. I also request new JWT everytime when my app is opened, i.e, in my Splash page.
Now, if any request contains expired JWT, simply return a common response like "Session expired" with a fixed status code. If any HTTP request has this specific status code in its response, I requested another API call with the refresh token to get fresh JWT for future requests.
As I needed to add this check (whether contains "Session Expired") in every HTTP response, I wrote a common function and passed the HTTP responses via that method, so that, I do not need to rewrite or copy-paste every bit of it.
This requires very less code and minimal operation on both server and app end. My system has a JWT expiration time of 20 minutes and I haven't faced any problem till now. Worst what happens is, in a single request, user receives token expired, gets token, and recalls that function. This results in a slightly delayed operation for users that is already in my app continuously for more than 20 minutes. If any user is in my app for that long, it's a good problem to have, right? :)
It's not clear whether the users have to log-in in your app every time or session is held so that logged-in users can directly enter the app. If session is hold, just keep the refreshToken in app locally (SharedPref) and use that to get JWT every time the app is opened. If any user is misusing your API (scraping or for any other purpose), simply move that specific refresh token to a black-list so that this user doesn't get new JWT.
Please let me know if anything's not clear. Thanks.

User Session Management in RoR API for Android

I am building an API in RoR to be used by an android app. I have looked at various other similar questions on SO but found nothing which fits my exact use case. I need to identify a logged in user and respond to the request accordingly. This goes just beyond getting the user id to user categories, implicit preferences (different from settings) to give the user a more personalized experience.
In a web app this is done through a session cookie using which I can essentially call the following methods:
current_user.id # Gets user's id
current_user.category # Gets user's category
current_user.auth_level #Gets user's permission level
To do this, in the webapp I have the following setup:
In login action:
...
#user_session = session_setter(email, password)
...
def session_setter(email,password)
#session = UserSession.new(:email => email, :password => password)
#session.save
end
UserSession.rb
class UserSession < Authlogic::Session::Base
logout_on_timeout true
last_request_at_threshold 100
skip_callback :persist, :persist_by_cookie
skip_callback :after_save, :save_cookie
skip_callback :after_destroy, :destroy_cookie
end
session_store.rb (configured for memcached)
require 'action_dispatch/middleware/session/dalli_store'
App::Application.config.session_store :dalli_store, :memcache_server => ['127.0.0.1:11211'], :key => '_session'
This setup allows me to access current_user object once the user is logged in and access all columns in the table users.
For android, this is what I have figured out:
Create an api_key for each user who creates an account. This could have an expiry date. Maintain and store this key in the users table. The api_key is passed on to the app on the first request where it is stored in something like sharedPreferences. Every request should carry the api_key to the server. Put filters on actions which require the user to be logged in, to check if the key is present or not.
Now, here is my question: In this setup I would need to retrieve the users record from the table (or store it in the memcached with the api_key as a key value pair) on every request through the filter.Is there a way to use something like current_user with the api?
In short I want to to replicate the same strategy for maintaining logged in users for the api as I have for the web app.
API is supposed to be unaware of your web-app contexts.
API is the classical stateless HTTP.
You ask it a question, it gives you answers. Albeit, from your web app's state and data, but it has no concern with what goes on at that end.
An API cannot, or rather, should not be coupled with the user logged in/ logged out state.
It is your webapp's responsibility to query the API with as much information it needs to reflect the logged in state.
Eg.,
If your API has a method get_recommendations,
it should ideally take in multiple args, to be able to handle all cases
logged out users, will make the query, wrt the page being viewed. As in, a matrix movie scene being viewed, should give other matrix scenes as reco's
logged in users, will make the query, wrt other aspects. As in, how many action videos has been viewed by this user, can be passed in as an arg.
The API endpoint should have the ability to handle both these scenarios seamlessly.
Make other calls to other methods if need be, to find out the current user's (identified by a user id key passed in) details.
So, from a design perspective, you should not pass in anything other than the fact that this request is for a signed in user with id = X.
Let your API handle everything else.
API is nothing but a special function/method.
Methods can do pretty much anything, as long as they remain true to their description / signature.

How does one deal with asynchronous login?

I am using Parse API for my app and I am going to be using the ParseUser object to maintain a user database. At the beginning, the user will be logged in using the logInInBackground() method.
Now, say that the connection is slow and the login is taking time or as soon as the user hits the sign up / sign in button, he gets a call and the activity is suspended. The call can go on for a long time (if the user is a blabber mouth) while the login/signup process continues in the background.
If it is successful, a new Activity is to be started or if it fails, an error message is to be displayed. However, since the Activity is suspended, how do I deal with it?
Do I keep some booleans, update SharedPreferences or what?
I know that in onPause() and onStop() background tasks have to be stopped.
Reference: https://www.parse.com/docs/android/api/?com/parse/ParseObject.html
Take a look at the User logon section of Rest API docs.
It walks u thru the process of submit a logon that sends a TOKEN in the response.
Note that at parse.com that token NEVER expires.
One usage on the client with a perpetual lease on the token is that you only have to log one time on one client. After that, assuming you do not need to switch among users, the SharedPreference persistence layer can keep the parse user token value for when its needed.
No logon step is necessary because any subsequent parse request can be accompany by the token.
I always use REST api. IMO parse only needs the token and not something like a user session.

Categories

Resources