verifyJwtHS256Signature function

JwtClaim verifyJwtHS256Signature(
  1. String token,
  2. String hmacKey, {
  3. JOSEHeaderCheck? headerCheck = defaultJWTHeaderCheck,
  4. bool defaultIatExp = true,
  5. Duration maxAge = JwtClaim.defaultMaxAge,
})

Verifies the signature and extracts the claim set from a JWT.

The signature is verified using the hmacKey with the HMAC SHA-256 algorithm.

The headerCheck is an optional function to check the header. It defaults to defaultJWTHeaderCheck.

Normally, if either the Issued At Claim and/or Expiration Time Claim are not present, default values are assigned to them. This behaviour can be disabled by setting defaultIatExp to false. See the constructor JwtClaim for details about what default values are used and how maxAge is used.

Throws a JwtException if the signature does not verify or the JWT is invalid.

final decClaimSet = verifyJwtHS256Signature(token, key);
print(decClaimSet);

Implementation

JwtClaim verifyJwtHS256Signature(String token, String hmacKey,
    {JOSEHeaderCheck? headerCheck = defaultJWTHeaderCheck,
    bool defaultIatExp = true,
    Duration maxAge = JwtClaim.defaultMaxAge}) {
  try {
    final hmac = Hmac(sha256, hmacKey.codeUnits);

    final parts = token.split('.');
    if (parts.length != 3) {
      throw JwtException.invalidToken;
    }

    // Decode header and payload
    final headerString = B64urlEncRfc7515.decodeUtf8(parts[0]);
    // Check header
    final dynamic header = json.decode(headerString);
    if (header is Map) {
      // Perform any custom checks on the header
      if (headerCheck != null &&
          !headerCheck(header.cast<String, dynamic?>())) {
        throw JwtException.invalidToken;
      }

      if (header['alg'] != 'HS256') {
        throw JwtException.hashMismatch;
      }
    } else {
      throw JwtException.headerNotJson;
    }

    // Verify signature: calculate signature and compare to token's signature
    final data = '${parts[0]}.${parts[1]}';
    final calcSig = hmac.convert(data.codeUnits).bytes;
    final tokenSig = B64urlEncRfc7515.decode(parts[2]);
    // Signature does not match calculated
    if (!secureCompareIntList(calcSig, tokenSig))
      throw JwtException.hashMismatch;

    // Convert payload into a claim set
    final payloadString = B64urlEncRfc7515.decodeUtf8(parts[1]);
    final dynamic payload = json.decode(payloadString);
    if (payload is Map) {
      return JwtClaim.fromMap(payload.cast(),
          defaultIatExp: defaultIatExp, maxAge: maxAge);
    } else {
      throw JwtException.payloadNotJson; // is JSON, but not a JSON object
    }
  } on FormatException {
    // Can be caused by:
    //   - header or payload parts are not Base64url Encoding
    //   - bytes in the header or payload are not proper UTF-8
    //   - string in header or payload cannot be parsed into JSON
    throw JwtException.invalidToken;
  }
}