···
final dpopKeyJwk = (dpopKey as dynamic).privateJwk ?? dpopKey.bareJwk ?? {};
479
-
print('๐ Storing DPoP key:');
480
-
print(' Has privateJwk: ${(dpopKey as dynamic).privateJwk != null}');
481
-
print(' Has bareJwk: ${dpopKey.bareJwk != null}');
482
-
print(' Stored JWK has "d" (private): ${dpopKeyJwk.containsKey('d')}');
483
-
print(' Stored JWK keys: ${dpopKeyJwk.keys.toList()}');
479
+
print('๐ Storing DPoP key for authorization flow');
···
// Create OAuth server agent
662
-
// TODO: Implement proper Key reconstruction from stored bareJwk
663
-
// For now, we regenerate the key with the same algorithms
664
-
// This works but is not ideal - we should restore the exact same key
stateData.authMethod != null
? ClientAuthMethod.fromJson(
···
: const ClientAuthMethod.none(); // Legacy fallback
// Restore dpopKey from stored private JWK
673
-
// Import FlutterKey to access fromJwk factory
675
-
print('๐ Restoring DPoP key:');
677
-
' Stored JWK has "d" (private): ${(stateData.dpopKey as Map).containsKey('d')}',
666
+
// Restore DPoP key with error handling for corrupted JWK data
667
+
final FlutterKey dpopKey;
669
+
dpopKey = FlutterKey.fromJwk(
670
+
stateData.dpopKey as Map<String, dynamic>,
680
-
' Stored JWK keys: ${(stateData.dpopKey as Map).keys.toList()}',
673
+
print('๐ DPoP key restored successfully for token exchange');
677
+
'Failed to restore DPoP key from stored state: $e. '
678
+
'The stored key may be corrupted. Please try authenticating again.',
684
-
final dpopKey = FlutterKey.fromJwk(
685
-
stateData.dpopKey as Map<String, dynamic>,
689
-
print(' โ
DPoP key restored successfully');
final server = await serverFactory.fromIssuer(
···
: const ClientAuthMethod.none(); // Legacy
842
-
// TODO: Implement proper Key reconstruction from stored bareJwk
843
-
// For now, we regenerate the key
844
-
final dpopKey = await runtime.generateKey([fallbackAlg]);
832
+
// Restore dpopKey from stored private JWK with error handling
833
+
// CRITICAL FIX: Use the stored key instead of generating a new one
834
+
// This ensures DPoP proofs match the token binding
835
+
final FlutterKey dpopKey;
837
+
dpopKey = FlutterKey.fromJwk(
838
+
session.dpopKey as Map<String, dynamic>,
841
+
// If key is corrupted, delete the session and force re-authentication
842
+
await _sessionGetter.delStored(
844
+
Exception('Corrupted DPoP key in stored session: $e'),
847
+
'Failed to restore DPoP key for session. The stored key is corrupted. '
848
+
'Please authenticate again.',
final server = await serverFactory.fromIssuer(
···
: const ClientAuthMethod.none(); // Legacy
898
-
// TODO: Implement proper Key reconstruction from stored bareJwk
899
-
// For now, we regenerate the key
900
-
final dpopKey = await runtime.generateKey([fallbackAlg]);
904
+
// Restore dpopKey from stored private JWK with error handling
905
+
// CRITICAL FIX: Use the stored key instead of generating a new one
906
+
// This ensures DPoP proofs match the token binding
907
+
final FlutterKey dpopKey;
909
+
dpopKey = FlutterKey.fromJwk(
910
+
session.dpopKey as Map<String, dynamic>,
913
+
// If key is corrupted, skip server-side revocation
914
+
// The finally block will still delete the local session
916
+
print('โ ๏ธ Cannot revoke on server: corrupted DPoP key ($e)');
917
+
print(' Local session will still be deleted');
final server = await serverFactory.fromIssuer(