verify static method

JWT verify(
  1. String token,
  2. JWTKey key, {
  3. bool checkHeaderType = true,
  4. bool checkExpiresIn = true,
  5. bool checkNotBefore = true,
  6. Duration? issueAt,
  7. String? subject,
  8. String? issuer,
  9. String? jwtId,
})

Verify Token

Implementation

static JWT verify(
  String token,
  JWTKey key, {
  bool checkHeaderType = true,
  bool checkExpiresIn = true,
  bool checkNotBefore = true,
  Duration? issueAt,
  String? subject,
  String? issuer,
  String? jwtId,
}) {
  try {
    final parts = token.split('.');
    final header = jsonBase64.decode(base64Padded(parts[0]));

    if (header == null || header is! Map<String, dynamic>) {
      throw JWTInvalidError('invalid header');
    }

    if (checkHeaderType && header['typ'] != 'JWT') {
      throw JWTInvalidError('not a jwt');
    }

    final algorithm = JWTAlgorithm.fromName(header['alg']);

    final body = utf8.encode('${parts[0]}.${parts[1]}');
    final signature = base64Url.decode(base64Padded(parts[2]));

    if (!algorithm.verify(key, Uint8List.fromList(body), signature)) {
      throw JWTInvalidError('invalid signature');
    }

    dynamic payload;

    try {
      payload = jsonBase64.decode(base64Padded(parts[1]));
    } catch (ex) {
      payload = utf8.decode(base64.decode(base64Padded(parts[1])));
    }

    if (payload is Map) {
      // exp
      if (checkExpiresIn && payload.containsKey('exp')) {
        final exp = DateTime.fromMillisecondsSinceEpoch(
          payload['exp'] * 1000,
        );
        if (exp.isBefore(DateTime.now())) {
          throw JWTExpiredError();
        }
      }

      // nbf
      if (checkNotBefore && payload.containsKey('nbf')) {
        final nbf = DateTime.fromMillisecondsSinceEpoch(
          payload['nbf'] * 1000,
        );
        if (nbf.isAfter(DateTime.now())) {
          throw JWTNotActiveError();
        }
      }

      // iat
      if (issueAt != null) {
        if (!payload.containsKey('iat')) {
          throw JWTInvalidError('invalid issue at');
        }
        final iat = DateTime.fromMillisecondsSinceEpoch(
          payload['iat'] * 1000,
        );
        if (!iat.isAtSameMomentAs(DateTime.now())) {
          throw JWTInvalidError('invalid issue at');
        }
      }

      // sub
      if (subject != null) {
        if (!payload.containsKey('sub') || payload['sub'] != subject) {
          throw JWTInvalidError('invalid subject');
        }
      }

      // iss
      if (issuer != null) {
        if (!payload.containsKey('iss') || payload['iss'] != issuer) {
          throw JWTInvalidError('invalid issuer');
        }
      }

      // jti
      if (jwtId != null) {
        if (!payload.containsKey('jti') || payload['jti'] != jwtId) {
          throw JWTInvalidError('invalid jwt id');
        }
      }

      return JWT(
        payload,
        header: header,
        issuer: payload['iss'],
        subject: payload['sub'],
        jwtId: payload['jti'],
      );
    } else {
      return JWT(payload);
    }
  } catch (ex) {
    if (ex is Error && ex is! JWTError) {
      throw JWTUndefinedError(ex);
    } else {
      rethrow;
    }
  }
}