import 'dart:convert'; import 'dart:developer'; import 'package:equatable/equatable.dart'; class AuthToken extends Equatable { final String accessToken; final DateTime expiresAt; final bool tnc; const AuthToken({ required this.accessToken, required this.expiresAt, required this.tnc, }); factory AuthToken.fromJson(Map json) { final token = json['token']; // Safely extract tnc.mobile directly from the outer JSON bool tncMobileValue = false; // Default to false if not found or invalid if (json.containsKey('tnc') && json['tnc'] is Map) { final tncMap = json['tnc'] as Map; if (tncMap.containsKey('mobile') && tncMap['mobile'] is bool) { tncMobileValue = tncMap['mobile'] as bool; } } return AuthToken( accessToken: token, expiresAt: _decodeExpiryFromToken( token), // This method is still valid for JWT expiry tnc: tncMobileValue, // Use the correctly extracted value ); } static DateTime _decodeExpiryFromToken(String token) { try { final parts = token.split('.'); if (parts.length != 3) { throw Exception('Invalid JWT'); } final payload = parts[1]; // Pad the payload if necessary String normalized = base64Url.normalize(payload); final payloadMap = json.decode(utf8.decode(base64Url.decode(normalized))); if (payloadMap is! Map || !payloadMap.containsKey('exp')) { throw Exception('Invalid payload'); } final exp = payloadMap['exp']; return DateTime.fromMillisecondsSinceEpoch(exp * 1000); } catch (e) { // Fallback: 1 hour from now if decoding fails log(e.toString()); return DateTime.now().add(const Duration(hours: 1)); } } // static bool _decodeTncFromToken(String token) { // try { // final parts = token.split('.'); // if (parts.length != 3) { // throw Exception('Invalid JWT format for TNC decoding'); // } // final payload = parts[1]; // String normalized = base64Url.normalize(payload); // final payloadMap = json.decode(utf8.decode(base64Url.decode(normalized))); // if (payloadMap is! Map || !payloadMap.containsKey('tnc')) { // // If 'tnc' is not present in the payload, default to false // return false; // } // final tncValue = payloadMap['tnc']; // // Handle different representations of 'true' // if (tncValue is bool) { // return tncValue; // } // if (tncValue is String) { // return tncValue.toLowerCase() == 'true'; // } // if (tncValue is int) { // return tncValue == 1; // } // // Default to false for any other case // return false; // } catch (e) { // log('Error decoding tnc from token: $e'); // // Default to false if decoding fails or 'tnc' is not found/invalid // return false; // } // } bool get isExpired => DateTime.now().isAfter(expiresAt); @override List get props => [accessToken, expiresAt, tnc]; }