authenticate method

  1. @override
Future<User?> authenticate(
  1. RequestContext req,
  2. ResponseContext res, [
  3. AngelAuthOptions? options
])
override

Authenticates or rejects an incoming user.

Implementation

@override
Future<User?> authenticate(RequestContext req, ResponseContext res,
    [AngelAuthOptions? options]) async {
  var localOptions = options ?? AngelAuthOptions();
  User? verificationResult;

  if (allowBasic) {
    var authHeader = req.headers?.value('authorization') ?? '';

    if (_rgxBasic.hasMatch(authHeader)) {
      var base64AuthString = _rgxBasic.firstMatch(authHeader)?.group(1);
      if (base64AuthString == null) {
        return null;
      }
      var authString = String.fromCharCodes(base64.decode(base64AuthString));
      if (_rgxUsrPass.hasMatch(authString)) {
        Match usrPassMatch = _rgxUsrPass.firstMatch(authString)!;
        verificationResult =
            await verifier(usrPassMatch.group(1), usrPassMatch.group(2));
      } else {
        _log.warning('Bad request: $invalidMessage');
        throw AngelHttpException.badRequest(errors: [invalidMessage]);
      }

      if (verificationResult == null) {
        res
          ..statusCode = 401
          ..headers['www-authenticate'] = 'Basic realm="$realm"';
        await res.close();
        return null;
      }

      //Allow non-null to pass through
      //return verificationResult;
    }
  } else {
    var body = await req
        .parseBody()
        .then((_) => req.bodyAsMap)
        .catchError((_) => <String, dynamic>{});
    if (_validateString(body[usernameField]?.toString()) &&
        _validateString(body[passwordField]?.toString())) {
      verificationResult = await verifier(
          body[usernameField]?.toString(), body[passwordField]?.toString());
    }
  }

  // User authentication succeeded can return Map(one element), User(non null) or true
  if (verificationResult != null && verificationResult != false) {
    if (verificationResult is Map && verificationResult.isNotEmpty) {
      return verificationResult;
    } else if (verificationResult is! Map) {
      return verificationResult;
    }
  }

  // Force basic if set
  if (forceBasic) {
    //res.headers['www-authenticate'] = 'Basic realm="$realm"';
    res
      ..statusCode = 401
      ..headers['www-authenticate'] = 'Basic realm="$realm"';
    await res.close();
    return null;
  }

  // Redirect failed authentication
  if (localOptions.failureRedirect != null &&
      localOptions.failureRedirect!.isNotEmpty) {
    await res.redirect(localOptions.failureRedirect, code: 401);
    return null;
  }

  _log.info('Not authenticated');
  throw AngelHttpException.notAuthenticated();

  /*
  if (verificationResult is Map && verificationResult.isEmpty) {
    if (localOptions.failureRedirect != null &&
        localOptions.failureRedirect!.isNotEmpty) {
      await res.redirect(localOptions.failureRedirect, code: 401);
      return null;
    }

    if (forceBasic) {
      res.headers['www-authenticate'] = 'Basic realm="$realm"';
      return null;
    }

    return null;
  } else if (verificationResult != false ||
      (verificationResult is Map && verificationResult.isNotEmpty)) {
    return verificationResult;
  } else {
    _log.info('Not authenticated');
    throw AngelHttpException.notAuthenticated();
  }
  */
}