8

I receive jwt token from the api but i don't know how to extract the expire time from the token in Dart.

The token which is received

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InN1amVldGg5MTE3MUBnbWFpbC5jb20iLCJ1c2VySWQiOiI1ZThhZGFlNDIxMDg3MzM1ODBmNDA4NTgiLCJpYXQiOjE1ODYxNTgzMzYsImV4cCI6MTU4Njc2MzEzNn0.EwLTdRXaibNmcbuqVxzEDSfrW37z3eWYIxAifAUsT5I

4
  • 1
    please add your token example to question Commented Apr 6, 2020 at 8:24
  • @KirillMatrosov i have added the token
    – thinkcode
    Commented Apr 6, 2020 at 8:27
  • Have you tried some of the many packages which provides parsing of jwt tokens? pub.dev/packages?q=jwt . If yes, which ones? Commented Apr 6, 2020 at 8:28
  • @julemand101 i have not tried any packages
    – thinkcode
    Commented Apr 6, 2020 at 8:30

6 Answers 6

5

An elegant solution would be using the jwt_decoder package. https://pub.dev/packages/jwt_decoder

  1. flutter pub add jwt_decoder
  2. Import it:

import 'package:jwt_decoder/jwt_decoder.dart';

  1. Get all JWT properties:
    String yourToken = "Your JWT";
    Map<String, dynamic> decodedToken = JwtDecoder.decode(yourToken);

or check only the expiration if that's the case:

String yourToken = "Your JWT";
bool hasExpired = JwtDecoder.isExpired(yourToken);
2

You can easily use the jwt_decode package.

  1. install jwt_decode
flutter pub add jwt_decode
  1. check isExpired
 bool hasExpired = Jwt.isExpired(token);

following is package URL https://pub.dev/packages/jwt_decode

1

An alternative solution if you want to use a package:

Install corsac_jwt: https://pub.dev/packages/corsac_jwt#-installing-tab-

import 'package:corsac_jwt/corsac_jwt.dart';

import 'package:corsac_jwt/corsac_jwt.dart';

void main() {
  final parsed = JWT.parse('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InN1amVldGg5MTE3MUBnbWFpbC5jb20iLCJ1c2VySWQiOiI1ZThhZGFlNDIxMDg3MzM1ODBmNDA4NTgiLCJpYXQiOjE1ODYxNTgzMzYsImV4cCI6MTU4Njc2MzEzNn0.EwLTdRXaibNmcbuqVxzEDSfrW37z3eWYIxAifAUsT5I');
  print(DateTime.fromMillisecondsSinceEpoch(parsed.expiresAt * 1000, isUtc: true)); // 2020-04-13 07:32:16.000Z
}
0

You can do it by decoding it, Speaking in general, JWT token conssist two part (objects), in the above JWT the result of decoding it is :

{
  alg: "HS256",
  typ: "JWT"
}.
{
  email: "[email protected]",
  userId: "5e8adae42108733580f40858",
  iat: 1586158336,
  exp: 1586763136
}.

So the expire date is a timestamp (1586763136) which stand for Monday, April 13, 2020 7:32:16 AM.

How ?

import 'dart:convert';

Map<String, dynamic> parseJwt(String token) {
final parts = token.split('.');
if (parts.length != 3) {
  throw Exception('invalid token');
}

final payload = _decodeBase64(parts[1]);
final payloadMap = json.decode(payload);
if (payloadMap is! Map<String, dynamic>) {
  throw Exception('invalid payload');
}

  return payloadMap;
}

String _decodeBase64(String str) {
String output = str.replaceAll('-', '+').replaceAll('_', '/');

switch (output.length % 4) {
  case 0:
  break;
case 2:
  output += '==';
  break;
case 3:
  output += '=';
  break;
default:
  throw Exception('Illegal base64url string!"');
}

  return utf8.decode(base64Url.decode(output));
}

Dart code credits goes to :boformer

0

You should use dart:convert. With utf8 you will decode base64 and with json get Map object to call ["exp"] property

import 'dart:convert';
String decodeBase64(String toDecode) {
  String res;
  try {
    while (toDecode.length * 6 % 8 != 0) {
      toDecode += "=";
    }
    res = utf8.decode(base64.decode(toDecode));
  } catch (error) {
    throw Exception("decodeBase64([toDecode=$toDecode]) \n\t\terror: $error");
  }
  return res;
}

void main () {
  final token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InN1amVldGg5MTE3MUBnbWFpbC5jb20iLCJ1c2VySWQiOiI1ZThhZGFlNDIxMDg3MzM1ODBmNDA4NTgiLCJpYXQiOjE1ODYxNTgzMzYsImV4cCI6MTU4Njc2MzEzNn0.EwLTdRXaibNmcbuqVxzEDSfrW37z3eWYIxAifAUsT5I';
  final decoded = json.decode(decodeBase64(token.split(".")[1]));
  int exp = decoded["exp"];
  print(exp); // 1586763136
}
0

I solved it without using the package. The package hasn't been updated for the last 3 years (https://pub.dev/packages/jwt_decode).

I hope this helps someone, and if there's room for improvement, go ahead.

Future<bool> get isTokenExpired async {
    try {
      final token = await sessionId;

      if (token == null) return true;

      final parts = token.split('.');
      if (parts.length != 3) return true;

      final payload = parts[1];
      final normalized = base64Url.normalize(payload);
      final convertToUtf8 = utf8.decode(base64Url.decode(normalized));
      final Map<String, dynamic> data = jsonDecode(convertToUtf8);

      final expirationDate = getExpirationDate(data['exp']);

      return DateTime.now().isAfter(expirationDate);
    } catch (e) {
      return true;
    }
  }

DateTime getExpirationDate(int exp) {
    if (exp == 0) return DateTime.now();

    return DateTime.fromMillisecondsSinceEpoch(exp * 1000);
  }

Not the answer you're looking for? Browse other questions tagged or ask your own question.