Is there a way to reauthenticates user before all the stateful widgets resume in Flutter? I have multiple stateful widgets which does api calls on init state. The problem is when the auth token expires, it would log the user out without giving it a chance to fetch a new auth token since these requests are concurrent. I.e. When one request is fetching a new auth token, another request will not know and thus assume log the user out. I want to make sure a loading screen which re-authenticates the user is shown before other stateful widgets are added back to the hierarchy on resume.
I figure it out a way by pushing a new route on resume and disabling the back button. Its quick enough that they use doesn't even see the screen.
Related
I have a flutter app that creates Firebase listeners by calling .snapshots().listen() — this assumes I have an authenticated user.
Each widget that creates such Firebase listeners also listens for auth changes and calls .cancel() on each Firebase listener when the user logs out.
The problem is a minor race condition; when the user logs out the Firebase listener throws auth errors before my auth listener is triggered. This isn't causing a big issue but it's polluting the log with stack traces.
One solution that comes to mind is to store my Firebase listeners in a global state object and call cancel() before logging the user out. That feels messy and I'm hoping someone can suggest a nicer approach. Thanks!
I'm using a Cubit-repository-datasource design separated by feature.
Title mostly says it all, but to extrapolate: I have an authentication Cubit. It is under the /authentication feature. I have another feature, /posts , that needs an access token from the /authentication feature to send an API request. This token is provided to it from the widget tree (authentication cubit is provided from the top of the widget tree). When a method from /posts's cubit is called: getPosts(int numOfPosts, String accessToken), it takes an access token from the provided widget tree's authentication cubit and passes it to the posts cubit. From here, it sends the request down to the repository layer, then to the data layer.
HOWEVER, what happens if the token is invalid? What happens if it has been tampered with? What happens if it's null? Then, I'd like the token to first be refreshed, and then to repeat the same call for posts using the refreshed access token. However, that "refresh the access token" method is inside the authentication cubit, not the posts cubit. How then should I call it? Can I call the refreshAccessToken() method (inside the /authentication feature's repository or data layer) from inside the repository or data layer of the /posts feature?
Is this sort of "crossing-feature" bad?
Thanks!
I second the comment made by #FabriBertani. The bloc/cubit shouldn't know anything about how to get the posts. It should just do getPosts(int numberOfPosts).
That method should e.g. come from an interface (abstract class in Dart) which in turn is implemented in a different layer (e.g. data/repository/service layer).
That implementation can then in turn handle what is needed to fetch the data from your API. It could e.g. have an authentication service injected to it from where it gets the token.
I do not know how I can solve the following doubt, I have a GET request from my API and of course, I would like to save the parameters obtained in the application and not have to make every time I browse each activity a new GET request, as it would overload the server by the over-requests requested. What is the correct way to keep this temporary data while using the app?
My idea is that as soon as the application loads, an Activity SPLASH is shown and this same SPLASH, performs the API request and from here the data is kept. How should the implementation be done?
I've spent quite a bit of time trying to debug something and I could not find the culprit until I realized that Firestore snapshot listeners were calling themselves whenever a user signed out. Is this indeed what is happening? Does a snapshot listener call itself when an authenticated user becomes null? What is the purpose of this unexpected behavior and can we disable it?
If you have a snapshot listener attached to a query that is authorized by security rules, and the rules say the user must be signed in, then the listener will generate an error if the user is no longer signed in. This is expected, and necessary to tell the client app that the query is no longer valid.
I've developing my first iOS app which allows users to login to an account on our website, and view / add / edit / delete records in a database.
I've written a basic app which handles the process like this;
App starts running.
Each view controller calls a checkAuth method from within the viewWillAppear method. This method gets the username and password stored within the app, sends them to the server as GET variables in a dataWithContentsOfURL request. The resulting JSON is then checked, if the response is a failure, then an alert dialog is shown, and the user is taken to a different tab (I'm using a tab bar controller) where they are prompted to enter their login details.
Using this method, every time a different view controller takes over (each scene in my storyboard file), the auth method is called. This seems a little wasteful. Is there a better way of ensuring a users login credentials are correct?
Thanks.
Storing the username and password in the app is bad practice. If modifying the back end is within your control, it would be better to authenticate to the back end, and get back a token that is only good for that device.
From here, you pass the token along with each request, and if the back end determines you have logged out then it should return an error message. This way, the authentication would be checked on an ad-hoc basis and only when sending a request.
I see no reason to do it every time a view loads, unless there is a business requirement for this.
Why don't you use a "communication management" singleton for this? It would handle all the tasks of authenticating and communicating with the server, and each one of your controllers talks to it without directly interacting with the server.
You could have an inactivity session timeout: via NSTimer.
Set a session timeout marker on successful login (e.g. login time plus 10 minutes).
As the user uses the app keep updating the stored session timeout time to the current time plus 10 minutes (invalidate the timer and create a new one).
When app exits or goes into background invalidate the timer.
Have the timer call a logout method when the timer times out.
Oh, and don't store username/password in the app. Use the keychain to store them encrypted (if necessary to keep them local). I suggest only the username should be stored locally.