philiprehberger_jwt_decoder

Tests pub package Last updated

Lightweight JWT token decoder with typed claim access and expiration checking

Requirements

  • Dart >= 3.6

Installation

Add to your pubspec.yaml:

dependencies:
  philiprehberger_jwt_decoder: ^0.5.0

Then run:

dart pub get

Usage

import 'package:philiprehberger_jwt_decoder/jwt_decoder.dart';

final payload = JwtDecoder.decode(token);
print(payload.subject);    // user-123
print(payload.expiration); // 2026-04-04 12:00:00.000

Check Expiration

if (JwtDecoder.isExpired(token)) {
  print('Token has expired');
}

final remaining = JwtDecoder.timeToExpiry(token);
print('Expires in ${remaining?.inMinutes} minutes');

Validate Structure

if (JwtDecoder.isValid(token)) {
  print('Token has valid JWT structure');
}

Clock Skew Tolerance

JwtDecoder.isExpired(token, clockSkew: Duration(seconds: 30));

Header Inspection

import 'package:philiprehberger_jwt_decoder/philiprehberger_jwt_decoder.dart';

final header = JwtDecoder.decodeHeader(token);
print(header['alg']); // "HS256"
print(header['typ']); // "JWT"

final alg = JwtDecoder.algorithm(token); // "HS256"

Safe Decoding

// Returns null instead of throwing on malformed tokens
final payload = JwtDecoder.tryDecode(token);
if (payload != null) {
  print(payload.subject);
}

final header = JwtDecoder.tryDecodeHeader(token);

Custom Claims

final payload = JwtDecoder.decode(token);
final role = payload.claim<String>('role');     // 'admin'
final level = payload.claim<int>('level');      // 5

Audience (RFC 7519)

final payload = JwtDecoder.decode(token);
// Always returns a list, whether aud is a string or array
final audiences = payload.audienceList; // ['app-1', 'app-2']

Not-Before Validation

if (JwtDecoder.isNotYetValid(token)) {
  print('Token is not yet valid');
}

// With clock skew tolerance
JwtDecoder.isNotYetValid(token, clockSkew: Duration(seconds: 30));

API

Method Description
JwtDecoder.decode(token) Decode a JWT and return its payload
JwtDecoder.tryDecode(token) Decode a JWT, or return null if malformed
JwtDecoder.decodeHeader(token) Decode the JWT header and return the claims map
JwtDecoder.tryDecodeHeader(token) Decode the JWT header, or return null if malformed
JwtDecoder.algorithm(token) Get the alg claim from the header
JwtDecoder.isValid(token) Check if a token has valid JWT structure
JwtDecoder.isExpired(token, {clockSkew}) Check if a token has expired
JwtDecoder.timeToExpiry(token) Get remaining time until expiration
JwtPayload.subject The sub claim
JwtPayload.issuer The iss claim
JwtPayload.audience The aud claim
JwtPayload.jwtId The jti claim
JwtPayload.issuedAt The iat claim as DateTime
JwtPayload.expiration The exp claim as DateTime
JwtPayload.notBefore The nbf claim as DateTime
JwtPayload.audienceList The aud claim as a list (handles both string and array)
JwtDecoder.isNotYetValid(token, {clockSkew}) Check if a token's nbf claim is in the future
JwtPayload.claim<T>(key) Get any custom claim by key

Development

dart pub get
dart analyze --fatal-infos
dart test

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

Libraries

jwt_decoder
philiprehberger_jwt_decoder
Lightweight JWT token decoder with typed claim access and expiration checking.