fix(jwt): make authTime optional (#227)

This commit is contained in:
Felix Angelov
2023-04-04 14:28:48 -05:00
committed by GitHub
parent 98eba79619
commit e2b7965231
5 changed files with 35 additions and 7 deletions
+4 -1
View File
@@ -4,4 +4,7 @@
.dart_tool/
.packages
build/
pubspec.lock
pubspec.lock
# Test related files
coverage/
+7 -3
View File
@@ -149,9 +149,13 @@ void _verifyPayload(JwtPayload payload, String issuer, String audience) {
throw const JwtVerificationFailure('Token issued at a future time.');
}
final authTime = DateTime.fromMillisecondsSinceEpoch(payload.authTime * 1000);
if (authTime.isAfter(now)) {
throw const JwtVerificationFailure('Authenticated at a future time.');
if (payload.authTime != null) {
final authTime = DateTime.fromMillisecondsSinceEpoch(
payload.authTime! * 1000,
);
if (authTime.isAfter(now)) {
throw const JwtVerificationFailure('Authenticated at a future time.');
}
}
if (payload.aud != audience) {
+2 -2
View File
@@ -14,7 +14,7 @@ class JwtPayload {
required this.aud,
required this.iss,
required this.sub,
required this.authTime,
this.authTime,
});
/// Decode a [JwtPayload] from a `Map<String, dynamic>`.
@@ -38,5 +38,5 @@ class JwtPayload {
final String sub;
/// Time when authentication occurred.
final int authTime;
final int? authTime;
}
@@ -18,7 +18,7 @@ JwtPayload _$JwtPayloadFromJson(Map<String, dynamic> json) => $checkedCreate(
aud: $checkedConvert('aud', (v) => v as String),
iss: $checkedConvert('iss', (v) => v as String),
sub: $checkedConvert('sub', (v) => v as String),
authTime: $checkedConvert('auth_time', (v) => v as int),
authTime: $checkedConvert('auth_time', (v) => v as int?),
);
return val;
},
+21
View File
@@ -10,6 +10,8 @@ import 'package:test/test.dart';
void main() {
const token =
'''eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxMGM5MGJhNGMzNjYzNTE2ZTA3MDdkMGU5YTg5NDgxMDYyODUxNTgiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vbXktYXBwIiwiYXVkIjoibXktYXBwIiwiYXV0aF90aW1lIjoxNjQzNjg0MjY2LCJ1c2VyX2lkIjoiRzR1MzdXdk90dmVWR0pRb1pCWGpxcHVWazZWMiIsInN1YiI6Ikc0dTM3V3ZPdHZlVkdKUW9aQlhqcXB1Vms2VjIiLCJpYXQiOjE2NDM2ODQyNjYsImV4cCI6MTY0MzY4Nzg2NiwiZW1haWwiOiJ0ZXN0QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7ImVtYWlsIjpbInRlc3RAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoicGFzc3dvcmQifX0.bUWnX_XmR1d9EmeFeYSsK_CHU1u9NPIHgyaQueZ6urYOtxvuL_QodjPl0c9CBJwctwPnxVyRmkeNCw0oF9xBgph0NApLL4FIG6vpDPZfW9txZBYr8xIvaqvmD0diACENAQdjRT2XmyEdQ2-U7SsTonybHmLoU9FMQTjAgw4NCALQvExfB6rtQ9GDsOBt1xoBkB3Vo7a5OmugZ1aHXF69b8As6137-Dggf5qx5R3oLRFovICMMesQziE3vGi-WKcbQxSeiD-9a6ShPAhk41XiyjFGDEOtUCQo63uwQnMw3g0KVtC6bzIyFq-E91vhxumxXzxPYC-kg7iUYiSZy7Y-Aw''';
const tokenNoAuthTime =
'''eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxMGM5MGJhNGMzNjYzNTE2ZTA3MDdkMGU5YTg5NDgxMDYyODUxNTgiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vbXktYXBwIiwiYXVkIjoibXktYXBwIiwidXNlcl9pZCI6Ikc0dTM3V3ZPdHZlVkdKUW9aQlhqcXB1Vms2VjIiLCJzdWIiOiJHNHUzN1d2T3R2ZVZHSlFvWkJYanFwdVZrNlYyIiwiaWF0IjoxNjQzNjg0MjY2LCJleHAiOjE2NDM2ODc4NjYsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJ0ZXN0QGdtYWlsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6InBhc3N3b3JkIn19.ZWCadE43mUk43cPQdNCCi4WhDgB4ZsDT9rhPGQq_1uFPhzkVrCSRcjUhwkzH11VLap_MVurNvI_pGWbu9Z4CRPvGFzXPpuNveWy2qFPEa4jcM-R40vsbrP30vNnrp4PrmqgLar0vWs6FZ2g9fbjU8L1LaU5ik31OKSXufTIKn_hPHhyIC33tYTpWzG3Abq3H9EELHUXKW9nEcN8YYnOHAZ3A6ymb3DyBguhf2O-XAIlrn1WoxRRqlukFGSmprk7heonbVUTzoc3sIDZcC-Cj1U9wTee1NmqmU7v3SvpBRGnuXz-5rzSRHblyVxn_EEfCYwjsDUwetYpyFcCs5dqPlQ''';
const publicKeysUrl =
'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com';
const issuer = 'https://securetoken.google.com/my-app';
@@ -133,6 +135,25 @@ void main() {
expect(jwt, isA<Jwt>());
});
});
test('can verify a valid jwt w/out auth_time', () async {
await withClock(Clock.fixed(validTime), () async {
getOverride = (Uri uri) async {
return Response(
body,
HttpStatus.ok,
headers: {'cache-control': 'max-age=3600'},
);
};
final jwt = await verify(
tokenNoAuthTime,
audience: audience,
issuer: issuer,
publicKeysUrl: publicKeysUrl,
);
expect(jwt, isA<Jwt>());
});
});
});
group('base64Padded', () {