verify method

Future<void> verify({
  1. String? issuer,
  2. String? audience,
  3. RSAPublicKey? publicKey,
})

Verify a signed JWT.

It is highly recommended to provide the issuer param, which prevents this method from fetching openid-configuration from unknown / malicious sources.

All of the following conditions must be true or else this method will throw:

  • iat (issued at) must be before now
  • exp (expiration) must be after now
  • kid (key id) must be set or publicKey must be non-null
  • iss (issuer) must be set
  • issuer must be null or equal to iss
  • audience must be null or equal to aud
  • signature must be valid

The key signature is checked either against the given publicKey, or the key that is provided by the issuers JWKS. JWKS keys are usually cached by KeyService.

Implementation

Future<void> verify({
  String? issuer,
  String? audience,
  RSAPublicKey? publicKey,
}) async {
  if (alg != 'RS256') {
    throw ApiRequestException.unauthorized(
        'Unsupported signing algorithm "$alg".');
  }

  if (iat?.isAfter(DateTime.now()) == true) {
    throw ApiRequestException.unauthorized('Invalid issue timestamp.');
  }

  if (exp?.isBefore(DateTime.now()) == true) {
    throw ApiRequestException.unauthorized('Token expired.');
  }

  if (kid == null && publicKey == null) {
    throw ApiRequestException.unauthorized('Missing key id in token header.');
  }

  if (iss == null) {
    throw ApiRequestException.unauthorized('Missing issuer in token.');
  }

  if (issuer != null && iss != issuer) {
    throw ApiRequestException.unauthorized('Issuer mismatch.');
  }

  if (audience != null && aud != audience) {
    throw ApiRequestException.unauthorized('Audience mismatch.');
  }

  final key = publicKey ??
      await resolve<KeyService>().getKey(Uri.parse(iss!), alg!, kid!);

  final body = utf8.encode(token.split('.').take(2).join('.'));
  final signer = Signer('SHA-256/RSA');
  signer.init(false, PublicKeyParameter<RSAPublicKey>(key));
  if (signer.verifySignature(
      Uint8List.fromList(body), RSASignature(signature))) {
    return;
  }

  throw ApiRequestException.unauthorized('Invalid signature.');
}