Skip to content

Commit c818077

Browse files
authored
Drop pkg:jose (#194)
1 parent 3836aaf commit c818077

File tree

4 files changed

+44
-31
lines changed

4 files changed

+44
-31
lines changed

packages/dart_firebase_admin/example_server_app/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies:
99
git:
1010
url: https://github.com/invertase/dart_firebase_admin.git
1111
path: packages/dart_firebase_admin
12-
ref: next
12+
ref: main
1313
shelf: ^1.4.2
1414
shelf_router: ^1.1.2
1515

packages/dart_firebase_admin/lib/src/utils/jwt.dart

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'dart:convert';
22

33
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
44
import 'package:http/http.dart' as http;
5-
import 'package:jose/jose.dart';
65
import 'package:meta/meta.dart';
76

87
const algorithmRS256 = 'RS256';
@@ -41,19 +40,19 @@ abstract class SignatureVerifier {
4140
}
4241

4342
abstract class KeyFetcher {
44-
Future<JsonWebKeyStore> fetchPublicKeys();
43+
Future<Map<String, JWTKey>> fetchPublicKeys();
4544
}
4645

4746
class UrlKeyFetcher implements KeyFetcher {
4847
UrlKeyFetcher(this.clientCert);
4948

5049
final Uri clientCert;
5150

52-
JsonWebKeyStore? _publicKeys;
51+
Map<String, JWTKey>? _publicKeys;
5352
late DateTime _publicKeysExpireAt;
5453

5554
@override
56-
Future<JsonWebKeyStore> fetchPublicKeys() async {
55+
Future<Map<String, JWTKey>> fetchPublicKeys() async {
5756
if (_shouldRefresh()) return refresh();
5857
return _publicKeys!;
5958
}
@@ -63,7 +62,7 @@ class UrlKeyFetcher implements KeyFetcher {
6362
return _publicKeysExpireAt.isBefore(DateTime.now());
6463
}
6564

66-
Future<JsonWebKeyStore> refresh() async {
65+
Future<Map<String, JWTKey>> refresh() async {
6766
final response = await http.get(clientCert);
6867
final json = jsonDecode(response.body) as Map<String, Object?>;
6968
final error = json['error'];
@@ -91,26 +90,27 @@ class UrlKeyFetcher implements KeyFetcher {
9190
}
9291
}
9392

94-
final store = _publicKeys = JsonWebKeyStore();
93+
final keys = <String, JWTKey>{};
9594

9695
for (final entry in json.entries) {
97-
final key = JsonWebKey.fromPem(entry.value! as String, keyId: entry.key);
98-
store.addKey(key);
96+
final pem = entry.value! as String;
97+
// Google X.509 certs are RSA
98+
keys[entry.key] = RSAPublicKey.cert(pem);
9999
}
100100

101-
return store;
101+
return _publicKeys = keys;
102102
}
103103
}
104104

105105
class JwksFetcher implements KeyFetcher {
106106
JwksFetcher(this.jwksUrl);
107107
final Uri jwksUrl;
108-
JsonWebKeyStore? _publicKeys;
108+
Map<String, JWTKey>? _publicKeys;
109109
int _publicKeysExpireAt = 0;
110110
static const int hourInMilliseconds = 6 * 60 * 60 * 1000; // 6 hours
111111

112112
@override
113-
Future<JsonWebKeyStore> fetchPublicKeys() async {
113+
Future<Map<String, JWTKey>> fetchPublicKeys() async {
114114
if (_shouldRefresh) return refresh();
115115

116116
return _publicKeys!;
@@ -121,27 +121,36 @@ class JwksFetcher implements KeyFetcher {
121121
_publicKeysExpireAt <= DateTime.now().millisecondsSinceEpoch;
122122
}
123123

124-
Future<JsonWebKeyStore> refresh() async {
124+
Future<Map<String, JWTKey>> refresh() async {
125125
final response = await http.get(jwksUrl);
126126
if (response.statusCode != 200) {
127127
throw Exception('Failed to fetch JWKS');
128128
}
129129

130130
final jwks = jsonDecode(response.body) as Map<String, dynamic>;
131-
final keys = JsonWebKeySet.fromJson(jwks).keys;
131+
final jwkList = jwks['keys'] as List<dynamic>?;
132+
133+
if (jwkList == null) {
134+
throw Exception('Invalid JWKS: missing "keys" array');
135+
}
132136

133137
// Reset expire time
134138
_publicKeysExpireAt = 0;
135139

136-
// Extract signing keys
137-
final store = _publicKeys = JsonWebKeyStore();
138-
keys.forEach(store.addKey);
140+
final newKeys = <String, JWTKey>{};
141+
for (final jwkJson in jwkList) {
142+
final jwk = jwkJson as Map<String, dynamic>;
143+
final kid = jwk['kid'] as String?;
144+
if (kid != null) {
145+
newKeys[kid] = JWTKey.fromJWK(jwk);
146+
}
147+
}
139148

140149
// Set new expiration time
141150
_publicKeysExpireAt =
142151
DateTime.now().millisecondsSinceEpoch + hourInMilliseconds;
143152

144-
return store;
153+
return _publicKeys = newKeys;
145154
}
146155
}
147156

@@ -175,10 +184,15 @@ class PublicKeySignatureVerifier implements SignatureVerifier {
175184
);
176185
}
177186

178-
final store = await keyFetcher.fetchPublicKeys();
187+
final keys = await keyFetcher.fetchPublicKeys();
188+
final key = keys[kid];
189+
190+
if (key == null) {
191+
throw JwtException(JwtErrorCode.noMatchingKid, 'no-matching-kid-error');
192+
}
179193

180194
try {
181-
await JsonWebToken.decodeAndVerify(token, store);
195+
JWT.verify(token, key);
182196
} catch (e, stackTrace) {
183197
Error.throwWithStackTrace(
184198
JwtException(
@@ -194,7 +208,9 @@ class PublicKeySignatureVerifier implements SignatureVerifier {
194208
} on JWTException catch (e) {
195209
throw JwtException(
196210
JwtErrorCode.unknown,
197-
e is JWTUndefinedException ? e.message : '${e.runtimeType}: e.message',
211+
e is JWTUndefinedException
212+
? e.message
213+
: '${e.runtimeType}: ${e.message}',
198214
);
199215
}
200216
}

packages/dart_firebase_admin/pubspec.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ dependencies:
2323
googleapis_beta: ^9.0.0
2424
http: ^1.0.0
2525
intl: ^0.20.0
26-
jose: ^0.3.4
2726
meta: ^1.9.1
2827
pem: ^2.0.5
2928
pointycastle: ^3.7.0

packages/dart_firebase_admin/test/unit/auth/jwt_test.dart

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:dart_firebase_admin/src/utils/jwt.dart';
22
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
3-
import 'package:jose/jose.dart';
3+
import 'package:pointycastle/pointycastle.dart' as pc;
44
import 'package:test/test.dart';
55

66
import '../../fixtures/mock_service_account.dart';
@@ -231,14 +231,12 @@ void main() {
231231

232232
class _TestKeyFetcher implements KeyFetcher {
233233
@override
234-
Future<JsonWebKeyStore> fetchPublicKeys() async {
235-
final store = JsonWebKeyStore();
236-
237-
// Public key corresponding to the test private key above
238-
const key = mockPrivateKey;
239-
240-
store.addKey(JsonWebKey.fromPem(key, keyId: 'key1'));
234+
Future<Map<String, JWTKey>> fetchPublicKeys() async {
235+
final privateKey = RSAPrivateKey(mockPrivateKey);
236+
final publicKey = RSAPublicKey.raw(
237+
pc.RSAPublicKey(privateKey.key.n!, privateKey.key.publicExponent!),
238+
);
241239

242-
return store;
240+
return {'key1': publicKey};
243241
}
244242
}

0 commit comments

Comments
 (0)