tryParseJwt static method

Token? tryParseJwt(
  1. String jwt, {
  2. String? refreshToken,
})

Parses a JWT jwt and returns a Token seeded with the exp and scope / scopes / scp claims found in the payload.

The raw JWT string is stored as accessToken verbatim so it can be attached to requests as-is. refreshToken is null unless supplied explicitly; pass it for refresh-token flows.

Returns null if jwt is not a valid JWT (wrong segment count, undecodable payload, etc.). Never throws.

Note: this only parses the payload; it does NOT verify the signature. Treat the returned Token as authoritative only after the server has accepted it on a subsequent request.

Implementation

static Token? tryParseJwt(String jwt, {String? refreshToken}) {
  try {
    final parts = jwt.split('.');
    if (parts.length != 3) return null;

    final payloadJson = utf8.decode(
      base64Url.decode(base64Url.normalize(parts[1])),
    );
    final claims = jsonDecode(payloadJson);
    if (claims is! Map<String, dynamic>) return null;

    DateTime? expiresAt;
    final exp = claims['exp'];
    if (exp is int) {
      expiresAt =
          DateTime.fromMillisecondsSinceEpoch(exp * 1000, isUtc: true);
    }

    List<String> scopes = const [];
    final scopeClaim = claims['scope'] ?? claims['scp'] ?? claims['scopes'];
    if (scopeClaim is String && scopeClaim.isNotEmpty) {
      scopes = scopeClaim.split(' ').where((s) => s.isNotEmpty).toList();
    } else if (scopeClaim is List) {
      scopes = List<String>.unmodifiable(scopeClaim.cast<String>());
    }

    return Token(
      accessToken: jwt,
      refreshToken: refreshToken,
      expiresAt: expiresAt,
      scopes: scopes,
    );
  } catch (_) {
    return null;
  }
}