authenticate method Null safety

Future<AuthToken> authenticate(
  1. String? username,
  2. String? password,
  3. String? clientID,
  4. String? clientSecret,
  5. {Duration expiration = const Duration(hours: 24),
  6. List<AuthScope>? requestedScopes}
)

Authenticates a username and password of an ResourceOwner and returns an AuthToken upon success.

This method works with this instance's delegate to generate and store a new token if all credentials are correct. If credentials are not correct, it will throw the appropriate AuthRequestError.

After expiration, this token will no longer be valid.

Implementation

Future<AuthToken> authenticate(
  String? username,
  String? password,
  String? clientID,
  String? clientSecret, {
  Duration expiration = const Duration(hours: 24),
  List<AuthScope>? requestedScopes,
}) async {
  if (clientID == null) {
    throw AuthServerException(AuthRequestError.invalidClient, null);
  }

  final client = await getClient(clientID);
  if (client == null) {
    throw AuthServerException(AuthRequestError.invalidClient, null);
  }

  if (username == null || password == null) {
    throw AuthServerException(AuthRequestError.invalidRequest, client);
  }

  if (client.isPublic) {
    if (!(clientSecret == null || clientSecret == "")) {
      throw AuthServerException(AuthRequestError.invalidClient, client);
    }
  } else {
    if (clientSecret == null) {
      throw AuthServerException(AuthRequestError.invalidClient, client);
    }

    if (client.hashedSecret != hashPassword(clientSecret, client.salt!)) {
      throw AuthServerException(AuthRequestError.invalidClient, client);
    }
  }

  final authenticatable = await delegate.getResourceOwner(this, username);
  if (authenticatable == null) {
    throw AuthServerException(AuthRequestError.invalidGrant, client);
  }

  final dbSalt = authenticatable.salt!;
  final dbPassword = authenticatable.hashedPassword;
  final hash = hashPassword(password, dbSalt);
  if (hash != dbPassword) {
    throw AuthServerException(AuthRequestError.invalidGrant, client);
  }

  final validScopes =
      _validatedScopes(client, authenticatable, requestedScopes);
  final token = _generateToken(
    authenticatable.id,
    client.id,
    expiration.inSeconds,
    allowRefresh: !client.isPublic,
    scopes: validScopes,
  );
  await delegate.addToken(this, token);

  return token;
}