refresh method
Refreshes session using the DPoP-bound refresh token flow.
The authorization server is re-discovered from OAuthSession.issuer.
The DPoP key pair from the session is reused. The given session is
never mutated; a brand-new OAuthSession is returned and stored.
If the server rejects the refresh token with invalid_grant, the
session is deleted from the OAuthSessionStore and an
OAuthSessionRevokedException is thrown so callers can route the user
back through authorize.
Throws:
- OAuthException when no refresh token is available or the request fails.
- OAuthSessionRevokedException when the session has been revoked.
Implementation
Future<OAuthSession> refresh(final OAuthSession session) async {
final refreshToken = session.refreshToken;
if (refreshToken == null || refreshToken.isEmpty) {
throw OAuthException('No refresh token available');
}
// Single-flight: coalesce concurrent refreshes of the same account onto
// one shared future so the rotating refresh token is POSTed exactly once.
final inFlight = _inFlightRefreshes[session.sub];
if (inFlight != null) return inFlight;
final future = _refresh(session, refreshToken);
_inFlightRefreshes[session.sub] = future;
try {
return await future;
} finally {
_inFlightRefreshes.remove(session.sub);
}
}