Closed KhaledAlMana closed 9 months ago
Hi @KhaledAlMana,
Hope you are well. Thanks for your comments about the framework.
Re. the refreshToken method
Have you implemented the shouldRefreshToken
?
This will tell Nylo when when to refresh the token.
E.g.
@override
Future<bool> shouldRefreshToken() async {
User? user = Auth.user();
if (user.token.expiryDate.isPast()) {
// Check if the token is expired
// This will trigger the [refreshToken] method
return true;
}
return false;
}
The full docs are here, hope that helps :)
Hello @agordn52,
Yes, and during the debug, it is being invoked. However, refreshToken
isn't invoked and all I have no clue why.
@override
Future<RequestHeaders> setAuthHeaders(RequestHeaders headers) async {
AuthTokens? tokens = await StorageKey.userToken.read<AuthTokens>();
if (tokens?.accessToken != null) {
headers.addBearerToken(tokens?.accessToken ?? "");
}
return headers;
}
@override
Future<bool> shouldRefreshTokens() async {
try {
AuthTokens? tokens = await StorageKey.userToken.read<AuthTokens>();
if (tokens?.accessToken == null) {
return false;
}
// If the token is expired, where expiredAt is epoch time
// add 15 seconds to the expiry time to account for latency
if (tokens?.expiresAt != null &&
DateTime.now().isAfter(
tokens?.expiresAt!.subtract(Duration(seconds: 15)) ??
DateTime.now())) {
return true;
} else {
return false;
}
} catch (e) {
print(e);
return false;
}
}
@override
refreshToken(Dio dio) async {
// debug is not hitting this function, nor printing the below.
print("refreshing token");
AuthTokens? tokens = await StorageKey.userToken.read<AuthTokens>();
print(tokens?.refreshToken);
if (tokens?.refreshToken == null) {
await Auth.logout();
routeToInitial(navigationType: NavigationType.pushAndForgetAll);
return;
}
dynamic response = (await dio.post(baseUrl + "/auth/refresh",
options: Options(
headers: {"Authorization": "Bearer ${tokens?.refreshToken}"})))
.data();
// Save the new token
await StorageKey.userToken.store(response);
}
Hi @KhaledAlMana,
Thanks for sharing your code. I see a few things wrong that should be changed, please try the below 👍
@override
Future<RequestHeaders> setAuthHeaders(RequestHeaders headers) async {
AuthTokens? tokens = await StorageKey.userToken.read<AuthTokens>();
if (tokens?.accessToken != null) {
headers.addBearerToken(tokens?.accessToken ?? "");
}
return headers;
}
@override
Future<bool> shouldRefreshTokens() async {
AuthTokens? tokens = await StorageKey.userToken.read<AuthTokens>();
if (tokens?.accessToken == null) {
return true; // if accessToken is null then you should want to get a new 'AuthTokens'
}
// If the token is expired, where expiredAt is epoch time
// add 15 seconds to the expiry time to account for latency
if (DateTime.now().isAfter(tokens?.expiresAt?.subtract(Duration(seconds: 15)) ?? DateTime.now())) {
return true;
}
return false;
}
@override
refreshToken(Dio dio) async {
// debug is not hitting this function, nor printing the below.
print("refreshing token");
AuthTokens? tokens = await StorageKey.userToken.read<AuthTokens>();
print(tokens?.refreshToken);
if (tokens?.refreshToken == null) {
await Auth.logout();
routeToInitial(navigationType: NavigationType.pushAndForgetAll);
return;
}
dynamic response = (await dio.post(baseUrl + "/auth/refresh",
options: Options(
headers: {"Authorization": "Bearer ${tokens?.refreshToken}"})))
.data; // data() not a function, use data instead
// Save the new token
await StorageKey.userToken.store(response);
}
I'm going to close this as resolved.
If you need help understanding networking, the docs on nylo.dev are up-to-date so you'll be able to learn more 👍
Sorry, I have been busy lately.
I got the .data;
issue but the problem is that the function refreshToken
is still not being called.
After the latest update, I tested it again, it works fine.
Thank you @agordn52 for your support.
First of all, Thank you @agordn52 for this great framework.
I'm following the docs, and what has been mentioned in the issues/discussions.
refreshToken function isn't being invoked at all.
Noting that the approach was mentioned, I have to retry manually.
Did I miss anything?
If we refresh on request instead, would it be better? but what if I run parallel requests?
Update [29-01-2024]
This is the interceptor approach.
the refreshTokens function checks if a refresh token is needed then proceed. if condition to eliminate the recursion.
I had to skip the previous approach, but I still do not know how reactive this approach is. Especially with parallel requests scenario.