createTokens method
Creates a new token pair for the given auth user.
This is akin to creating a new session, and should be used after a successful login or registration.
Implementation
Future<AuthSuccess> createTokens(
final Session session, {
required final UuidValue authUserId,
required final String method,
/// The scopes to apply to the token.
///
/// By default forwards all of the [AuthUser]'s scopes to the session.
Set<Scope>? scopes,
/// Extra claims to be added to the JWT.
///
/// These are added on the top level of the payload, so be sure not to conflict with the [registered claims](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1),
/// as those will always overwrite any custom claims given here.
///
/// These claims will be embedded in every access token (also across rotations) and then sent along with any request. This should be taken into account with regard to the total size of the added claims.
final Map<String, dynamic>? extraClaims,
/// Whether to skip the check if the user is blocked (in which case a
/// [AuthUserBlockedException] would be thrown).
///
/// Should only to be used if the caller is sure that the user is not
/// blocked.
final bool skipUserBlockedChecked = false,
final Transaction? transaction,
}) async {
if (!skipUserBlockedChecked || scopes == null) {
final authUser = await authUsers.get(
session,
authUserId: authUserId,
transaction: transaction,
);
if (authUser.blocked && !skipUserBlockedChecked) {
throw AuthUserBlockedException();
}
scopes ??= authUser.scopes;
}
// Invoke the extra claims provider if configured
final mergedExtraClaims = config.extraClaimsProvider != null
? await config.extraClaimsProvider!(
session,
JwtContext(
authUserId: authUserId,
method: method,
scopes: scopes,
extraClaims: extraClaims,
),
)
: extraClaims;
final encodedExtraClaims =
mergedExtraClaims != null && mergedExtraClaims.isNotEmpty
? jsonEncode(mergedExtraClaims)
: null;
final secret = _generateRefreshTokenRotatingSecret();
final newHash = await refreshTokenSecretHash.createHashFromBytes(
secret: secret,
);
final currentTime = clock.now();
final refreshToken = await RefreshToken.db.insertRow(
session,
RefreshToken(
authUserId: authUserId,
fixedSecret: ByteData.sublistView(_generateRefreshTokenFixedSecret()),
rotatingSecretHash: newHash,
scopeNames: scopes.names,
extraClaims: encodedExtraClaims,
createdAt: currentTime,
lastUpdatedAt: currentTime,
method: method,
),
transaction: transaction,
);
final token = jwtUtil.createJwt(refreshToken);
return AuthSuccess(
authStrategy: AuthStrategy.jwt.name,
token: token,
tokenExpiresAt: jwtUtil.extractExpirationDate(token),
refreshToken: RefreshTokenString.buildRefreshTokenString(
refreshToken: refreshToken,
rotatingSecret: secret,
),
authUserId: authUserId,
scopeNames: scopes.names,
);
}