refreshToken method
Refreshes an access token
refreshToken The refresh token Returns new authentication response
Implementation
@override
Future<AuthResponse> refreshToken(String refreshToken) async {
// Extract session ID and raw token from the combined refresh token
final parts = refreshToken.split('::');
if (parts.length != 2) {
throw AuthException('Invalid refresh token format');
}
final sessionId = parts[0];
// For JWT, verify the refresh token from database
final tokenRecord = await _tokenService.findToken(refreshToken);
if (tokenRecord == null) {
throw AuthException('Invalid refresh token');
}
final tokenType = tokenRecord['type'] as String?;
if (tokenType != 'refresh') {
throw AuthException('Invalid token type for refresh');
}
// Check expiry
final expiry = _parseDateTime(tokenRecord['expires_at']);
if (expiry != null) {
if (DateTime.now().isAfter(expiry)) {
await _tokenService.deleteToken(refreshToken);
throw AuthException('Refresh token has expired');
}
}
final userId = tokenRecord['tokenable_id'];
// Get user data from database
final provider = _config.getProvider(_providerKey);
final table = provider['table'] as String;
final primaryKey = provider['primary_key'] as String;
// For user retrieval, we still need repository access
// This could be improved with a UserService interface
final repository = DatabaseAuthRepository();
final userData = await repository.findUserById(userId, table, primaryKey);
if (userData == null) {
throw AuthException('User not found');
}
final user = DatabaseAuthenticatable.fromProviderConfig(
userData,
provider,
);
// Generate new access token reusing the same session ID
final now = DateTime.now();
final payload = {
'sub': userId,
'iat': now.millisecondsSinceEpoch ~/ 1000,
'exp': now.add(_accessTokenExpiry).millisecondsSinceEpoch ~/ 1000,
'jti': sessionId, // Reuse the same session ID
'user': _sanitizeUserData(user.toAuthArray()),
};
final jwt = JWT(payload);
final newAccessToken = jwt.sign(SecretKey(_secret));
// Generate new refresh token with the same session ID
final rawRefreshToken = _tokenGenerator.generateToken();
final newRefreshToken = '$sessionId::$rawRefreshToken';
// Store new refresh token
final refreshTokenData = {
'token': newRefreshToken,
'tokenable_id': userId,
'guard': _providerKey,
'type': 'refresh',
'created_at': DateTime.now().toIso8601String(),
'expires_at': DateTime.now().add(_refreshTokenExpiry).toIso8601String(),
};
await _tokenService.storeToken(refreshTokenData);
// Clean up old refresh token
await _tokenService.deleteToken(refreshToken);
return AuthResponse(
user: user.toAuthArray(),
accessToken: newAccessToken,
refreshToken: newRefreshToken,
expiresIn: _accessTokenExpiry.inSeconds,
refreshExpiresIn: _refreshTokenExpiry.inSeconds,
);
}