fresh
fresh copied to clipboard
Possible race condition when using custom tokenStorage
Hi! First of all thanks for creating this package, this has been pretty helpful in my projects.
I've implemented the Fresh interceptor with a custom TokenStorage based on FlutterSecureStorage. After a successful login I call the write
method on the TokenStorage. When restarting the app, I would expect the token to be retrieved from the store before being returned, but the token is being returned while the Fresh is still in the idle status. This returns in an empty token, which will only later be updated after the authenticationStatus changes.
final StreamController<AuthenticationStatus> _controller =
StreamController<AuthenticationStatus>.broadcast()
..add(AuthenticationStatus.initial);
/// Setter for the [TokenStorage] instance.
set tokenStorage(TokenStorage<T> tokenStorage) {
_tokenStorage = tokenStorage..read().then(_updateStatus);
}
/// Returns the current token.
Future<T?> get token async {
if (_authenticationStatus != AuthenticationStatus.initial) return _token;
await authenticationStatus.first;
return _token;
}
The await authenticationStatus.first;
now actually awaits the AuthenticationStatus.initial
status while I would expect any status that is not an AuthenticationStatus.initial
.
In my project I fixed this by adding the following:
/// Ensures that fresh is initialized and not longer loading the token.
Future<void> ensureReady() async {
await fresh.authenticationStatus.firstWhere(
(authenticationStatus) => authenticationStatus != AuthenticationStatus.initial,
);
}
I think it would be nice if the token
getter awaits the first authenticationStatus
that is not AuthenticationStatus.initial
/// Returns the current token.
Future<T?> get token async {
if (_authenticationStatus != AuthenticationStatus.initial) return _token;
await fresh.authenticationStatus.firstWhere(
(authenticationStatus) => authenticationStatus != AuthenticationStatus.initial,
);
return _token;
}