You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Fresh package currently supports reactive token refresh via the shouldRefresh callback, which is triggered after requests. While this approach works well, many use cases (e.g., OAuth2 with expiresIn) can benefit from proactive token validation, where tokens are validated and refreshed before requests are made.
Proactively validating tokens:
Prevents sending expired tokens, reducing unnecessary backend errors (e.g., AUTH_NOT_AUTHENTICATED in GraphQL, 401 Unauthorized or invalid_token in REST APIs)
Improves efficiency by avoiding retries
This feature request proposes two potential solutions to enable proactive token validation in Fresh.
Proposed Solutions:
Here’s the updated GitHub issue with Option 1 (developer-managed logic) and Option 2 (built-in expiration handling with refreshIfExpired and enhanced OAuth2Token).
Option 1: Developer-Managed Expiration Logic
Introduce a validateTokenBeforeRequest callback, giving developers complete control over token expiration handling.
Example:
Fresh<OAuth2Token>(
tokenStorage: tokenStorage,
refreshToken: (token, client) async {
// Refresh token logic
},
shouldRefresh: (response) {
// GraphQL or REST should refresh logicreturn response.errors?.first.extensions?['code'] =='AUTH_NOT_AUTHENTICATED';
},
validateTokenBeforeRequest: (token) async {
final now =DateTime.now().millisecondsSinceEpoch /1000;
final issuedAt =awaitgetIssuedAtFromStorage(); // Developer handles issuedAtreturn token.expiresIn !=null&& issuedAt !=null? now >= (issuedAt + token.expiresIn!)
:false;
},
);
How It Works:
Fresh calls validateTokenBeforeRequest before every request.
Developers define custom expiration logic, such as using expiresIn and a custom issuedAt field.
If the token is expired, Fresh triggers the refreshToken callback to refresh it.
Pros:
Provides maximum flexibility.
Requires no changes to OAuth2Token or Fresh internals.
Fully backward compatible.
Cons:
Developers must manage and store issuedAt themselves.
Option 2 Built-In Expiration Handling with Enhanced OAuth2Token
Introduce a refreshIfExpired boolean and enhance OAuth2Token with an optional issuedAt field for built-in expiration logic.
Example:
classOAuth2Token {
constOAuth2Token({
requiredthis.accessToken,
this.tokenType ='bearer',
this.expiresIn,
this.refreshToken,
this.scope,
this.issuedAt, // Optional field for token issuance time
});
finalString accessToken;
finalString? tokenType;
finalint? expiresIn; // Duration in secondsfinalString? refreshToken;
finalString? scope;
finalint? issuedAt; // Timestamp or DateTime when the token was issued
}
Fresh<OAuth2Token>(
tokenStorage: tokenStorage,
refreshToken: (token, client) async {
// Refresh token logic
},
shouldRefresh: (response) {
// GraphQL or REST should refresh logicreturn response.errors?.first.extensions?['code'] =='AUTH_NOT_AUTHENTICATED';
},
refreshIfExpired:true, // Enable built-in expiration handling
);
How It Works:
Fresh uses expiresIn and issuedAt (if provided) to calculate the token's expiration time:
final expirationTime = token.issuedAt + token.expiresIn!;
if (DateTime.now().millisecondsSinceEpoch /1000>= expirationTime) {
awaitrefreshToken(token);
}
If the token is expired or nearing expiration, Fresh refreshes it before sending the request.
If issuedAt is not provided, developers can handle expiration manually via shouldRefresh.
Pros:
Simple to use: Enable refreshIfExpired and let Fresh handle expiration logic.
Customizable: Developers can provide issuedAt for precise expiration handling or rely on default behavior.
Fully backward compatible and opt-in.
Cons:
Requires modifying the OAuth2Token class to include an optional issuedAt field.
Adds slight complexity to Fresh internals.
The text was updated successfully, but these errors were encountered:
I opened #112 to attempt to refresh expired tokens proactively. Let me know if that addresses your concerns and/or if you have any feedback on the API, thanks! 🙏
Question how would people that want to persist the storage (for example : use FlutterSecureStorage) instead of using InMemoryTokenStorage be able to benefit from this great out of the box refresh mechanism ? They'd want _expiresAt to be stored in FlutterSecureStorage too & not just in cache
Description:
The
Fresh
package currently supports reactive token refresh via theshouldRefresh
callback, which is triggered after requests. While this approach works well, many use cases (e.g., OAuth2 withexpiresIn
) can benefit from proactive token validation, where tokens are validated and refreshed before requests are made.Proactively validating tokens:
This feature request proposes two potential solutions to enable proactive token validation in
Fresh
.Proposed Solutions:
Here’s the updated GitHub issue with Option 1 (developer-managed logic) and Option 2 (built-in expiration handling with
refreshIfExpired
and enhancedOAuth2Token
).Option 1: Developer-Managed Expiration Logic
Introduce a
validateTokenBeforeRequest
callback, giving developers complete control over token expiration handling.Example:
How It Works:
Fresh
callsvalidateTokenBeforeRequest
before every request.expiresIn
and a customissuedAt
field.Fresh
triggers therefreshToken
callback to refresh it.Pros:
OAuth2Token
orFresh
internals.Cons:
issuedAt
themselves.Option 2 Built-In Expiration Handling with Enhanced
OAuth2Token
Introduce a
refreshIfExpired
boolean and enhanceOAuth2Token
with an optionalissuedAt
field for built-in expiration logic.Example:
How It Works:
Fresh
usesexpiresIn
andissuedAt
(if provided) to calculate the token's expiration time:If the token is expired or nearing expiration,
Fresh
refreshes it before sending the request.If
issuedAt
is not provided, developers can handle expiration manually viashouldRefresh
.Pros:
refreshIfExpired
and letFresh
handle expiration logic.issuedAt
for precise expiration handling or rely on default behavior.Cons:
OAuth2Token
class to include an optionalissuedAt
field.Fresh
internals.The text was updated successfully, but these errors were encountered: