jwtPayload function

Map<String, Object?>? jwtPayload(
  1. String token
)

Decodes payload (middle part) as JSON map; returns null if invalid. Audited: 2026-06-12 11:26 EDT

Implementation

Map<String, Object?>? jwtPayload(String token) {
  // Validate structure first so the index access below is safe: isJwtStructure
  // guarantees exactly three non-empty parts, making the [1] read on the split
  // result an established invariant rather than an unchecked subscript.
  if (!isJwtStructure(token)) return null;
  // Decoding can fail many ways (bad base64url, non-UTF8 bytes, malformed JSON,
  // a non-object payload); catch broadly and report null rather than throwing
  // into the caller, logging only in debug to aid diagnosis.
  try {
    final String payload = token.split('.')[_jwtPayloadPartIndex];
    // base64url omits '=' padding, but base64Url.decode requires the length to be
    // a multiple of four — restore the stripped padding before decoding. The
    // outer `% block` keeps this at 0 when the length is already aligned;
    // `block - 0` would otherwise append a spurious full '====' block, making
    // the decoder reject an otherwise-valid token.
    final int padLen =
        (_base64PaddingBlockSize - payload.length % _base64PaddingBlockSize) %
        _base64PaddingBlockSize;
    final String padded = payload + '=' * padLen;
    final Uint8List bytes = Uint8List.fromList(base64Url.decode(padded));
    // Decode the bytes as UTF-8, not raw code units: a claim value with any
    // multi-byte character would otherwise become mojibake. Malformed UTF-8
    // throws and is caught below as an invalid payload.
    final String json = utf8.decode(bytes);
    final decoded = jsonDecode(json);
    // A well-formed JWT payload is a JSON object; anything else (array, scalar)
    // is not a claims set.
    if (decoded is! Map) return null;
    return Map<String, Object?>.from(decoded);
  } on Object catch (e, st) {
    if (kDebugMode) log(_kLogJwtPayloadFailed, error: e, stackTrace: st);
    return null;
  }
}