rotateRefreshToken method
Future<TokenPair>
rotateRefreshToken(
- Session session, {
- required String refreshToken,
- Transaction? transaction,
Returns a new refresh / access token pair.
This invalidates the previous refresh token. Previously created access tokens for this refresh token will continue to work until they expire.
Implementation
Future<TokenPair> rotateRefreshToken(
final Session session, {
required final String refreshToken,
final Transaction? transaction,
}) async {
final RefreshTokenStringData refreshTokenData;
try {
refreshTokenData = RefreshTokenString.parseRefreshTokenString(
refreshToken,
);
} catch (e, stackTrace) {
session.log(
'Received malformed refresh token',
exception: e,
stackTrace: stackTrace,
level: LogLevel.debug,
);
throw RefreshTokenMalformedServerException();
}
var refreshTokenRow = await RefreshToken.db.findById(
session,
refreshTokenData.id,
transaction: transaction,
);
if (refreshTokenRow == null ||
!uint8ListAreEqual(
Uint8List.sublistView(refreshTokenRow.fixedSecret),
refreshTokenData.fixedSecret,
)) {
throw RefreshTokenNotFoundServerException();
}
if (refreshTokenRow.isExpired(_refreshTokenLifetime)) {
await RefreshToken.db.deleteRow(
session,
refreshTokenRow,
transaction: transaction,
);
throw RefreshTokenExpiredServerException(
refreshTokenId: refreshTokenRow.id!,
authUserId: refreshTokenRow.authUserId,
);
}
if (!await _refreshTokenSecretHash.validateHashFromBytes(
secret: refreshTokenData.rotatingSecret,
hashString: refreshTokenRow.rotatingSecretHash,
)) {
await RefreshToken.db.deleteRow(
session,
refreshTokenRow,
transaction: transaction,
);
throw RefreshTokenInvalidSecretServerException(
refreshTokenId: refreshTokenRow.id!,
authUserId: refreshTokenRow.authUserId,
);
}
final newSecret = _generateRefreshTokenRotatingSecret();
final newHash = await _refreshTokenSecretHash.createHashFromBytes(
secret: newSecret,
);
refreshTokenRow = await RefreshToken.db.updateRow(
session,
refreshTokenRow.copyWith(
rotatingSecretHash: newHash,
lastUpdatedAt: clock.now(),
),
transaction: transaction,
);
return TokenPair(
refreshToken: RefreshTokenString.buildRefreshTokenString(
refreshToken: refreshTokenRow,
rotatingSecret: newSecret,
),
accessToken: _jwtUtil.createJwt(refreshTokenRow),
);
}