fix(jwt): make authTime optional (#227)
This commit is contained in:
@@ -4,4 +4,7 @@
|
||||
.dart_tool/
|
||||
.packages
|
||||
build/
|
||||
pubspec.lock
|
||||
pubspec.lock
|
||||
|
||||
# Test related files
|
||||
coverage/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
@@ -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', () {
|
||||
|
||||
Reference in New Issue
Block a user