login method

Future<void> login(
  1. TContext context,
  2. AuthPrincipal principal, {
  3. bool rememberMe = false,
  4. Duration? rememberDuration,
  5. bool rotateSession = true,
})

Logs in principal and stores it in the session and request context.

When rotateSession is true, the runtime invokes regenerateSession before writing state. rememberMe saves a one-time-rotated token using rememberDuration or defaultRememberDuration; a non-positive duration throws an ArgumentError. A non-remembered rotating login revokes any existing remember cookie.

Implementation

Future<void> login(
  TContext context,
  AuthPrincipal principal, {
  bool rememberMe = false,
  Duration? rememberDuration,
  bool rotateSession = true,
}) async {
  final safePrincipal = _safePrincipal(principal);
  if (safePrincipal.id.trim().isEmpty) {
    throw ArgumentError.value(
      principal.id,
      'principal.id',
      'must be non-empty',
    );
  }
  if (rotateSession) {
    regenerateSession?.call(context);
  }
  adapter.writeSessionPrincipal(
    context,
    sessionPrincipalKey,
    safePrincipal.toJson(),
  );
  adapter.writePrincipalAttribute(
    context,
    principalAttributeKey,
    safePrincipal,
  );

  if (!rememberMe) {
    if (rotateSession) {
      final existing = _findRequestCookie(context);
      if (existing != null && existing.value.isNotEmpty) {
        await Future.sync(() => rememberStore.remove(existing.value));
        adapter.setResponseCookie(
          context,
          adapter.buildExpiredRememberCookie(context, rememberCookieName),
        );
      }
    }
    return;
  }

  final duration = rememberDuration ?? defaultRememberDuration;
  if (duration <= Duration.zero) {
    throw ArgumentError.value(
      duration,
      'rememberDuration',
      'must be greater than zero',
    );
  }

  final existing = _findRequestCookie(context);
  if (existing != null && existing.value.isNotEmpty) {
    await Future.sync(() => rememberStore.remove(existing.value));
  }

  final token = _generatedRememberToken();
  final expiresAt = _clock().add(duration);
  await Future.sync(
    () => rememberStore.save(token, safePrincipal, expiresAt),
  );
  adapter.setResponseCookie(
    context,
    adapter.buildRememberCookie(
      context,
      rememberCookieName,
      token,
      expiresAt,
    ),
  );
}