createSession static method
Create a session for the user, returning the secret session key to be used for the authentication header.
The user should have been authenticated before calling this method.
A fixed expiresAt
can be set to ensure that the session is not usable after that date.
Additional expireAfterUnusedFor
can be set to make sure that the session has not been unused for longer than the provided value.
In case the session was unused for at least expireAfterUnusedFor
it'll automatically be decomissioned.
Send the return value to the client to use that to authenticate in future calls.
In most situations this should not be called directly, but rather through an authentication provider.
Implementation
@useResult
static Future<AuthSuccess> createSession(
final Session session, {
required final UuidValue authUserId,
required final String method,
/// The scopes to apply to the session.
///
/// By default forwards all of the [AuthUser]'s scopes to the session.
Set<Scope>? scopes,
/// Fixed date at which the session expires.
/// If `null` the session will work until it's deleted or when it's been
/// inactive for [expireAfterUnusedFor].
final DateTime? expiresAt,
/// Length of inactivity after which the session is no longer usable.
final Duration? expireAfterUnusedFor,
/// 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;
}
final secret = generateRandomBytes(config.sessionKeySecretLength);
final hash = _sessionKeyHash.createSessionKeyHash(secret: secret);
final scopeNames = <String>{
for (final scope in scopes)
if (scope.name != null) scope.name!,
};
final authSession = await AuthSession.db.insertRow(
session,
AuthSession(
authUserId: authUserId,
createdAt: clock.now(),
lastUsedAt: clock.now(),
expiresAt: expiresAt,
expireAfterUnusedFor: expireAfterUnusedFor,
scopeNames: scopeNames,
sessionKeyHash: ByteData.sublistView(hash.hash),
sessionKeySalt: ByteData.sublistView(hash.salt),
method: method,
),
transaction: transaction,
);
return AuthSuccess(
sessionKey: buildSessionKey(
secret: secret,
authSessionId: authSession.id!,
),
authUserId: authUserId,
scopeNames: scopeNames,
);
}