authenticationHandler static method

Future<AuthenticationInfo?> authenticationHandler(
  1. Session session,
  2. String key
)

Looks up the AuthenticationInfo belonging to the key.

Only looks at keys created with this package (by checking the prefix), returns null for all other inputs.

In case the session looks like it was created with this package, but does not resolve to a valid authentication info (anymore), this will return null, and log details of the reason for rejection.

Implementation

static Future<AuthenticationInfo?> authenticationHandler(
  final Session session,
  final String key,
) async {
  final sessionKeyParts = tryParseSessionKey(session, key);
  if (sessionKeyParts == null) {
    return null;
  }

  final (:authSessionId, :secret) = sessionKeyParts;

  var authSession = await AuthSession.db.findById(
    session,
    authSessionId,
  );

  if (authSession == null) {
    session.log(
      'Did not find auth session with ID "$authSessionId"',
      level: LogLevel.debug,
    );

    return null;
  }

  final expiresAt = authSession.expiresAt;
  if (expiresAt != null && clock.now().isAfter(expiresAt)) {
    session.log(
      'Got session after its set expiration date.',
      level: LogLevel.debug,
    );

    return null;
  }

  final expireAfterUnusedFor = authSession.expireAfterUnusedFor;
  if (expireAfterUnusedFor != null &&
      authSession.lastUsedAt
          .add(expireAfterUnusedFor)
          .isBefore(clock.now())) {
    session.log(
      'Got session which expired due to inactivity.',
      level: LogLevel.debug,
    );

    return null;
  }

  if (!_sessionKeyHash.validateSessionKeyHash(
    secret: secret,
    hash: Uint8List.sublistView(authSession.sessionKeyHash),
    salt: Uint8List.sublistView(authSession.sessionKeySalt),
  )) {
    session.log(
      'Provided `secret` did not result in correct session key hash.',
      level: LogLevel.debug,
    );

    return null;
  }

  if (authSession.lastUsedAt
      .isBefore(clock.now().subtract(const Duration(minutes: 1)))) {
    authSession = await AuthSession.db.updateRow(
      session,
      authSession.copyWith(lastUsedAt: clock.now()),
    );
  }

  return AuthenticationInfo(
    authSession.authUserId.uuid,
    authSession.scopeNames.map(Scope.new).toSet(),
    authId: authSessionId.toString(),
  );
}