Skip to content

Commit ba39bc2

Browse files
committed
fix(supabase_flutter): drop passkeys requireResidentKey workaround, bump dependency
The passkeys_platform_interface null cast crash from omitted authenticatorSelection.requireResidentKey (#1496) is now fixed upstream in corbado/flutter-passkeys#254, released as passkeys_platform_interface 2.8.0. Bump the dependency and revert the mapper workaround added in #1502, which is no longer needed.
1 parent a0580c7 commit ba39bc2

3 files changed

Lines changed: 5 additions & 73 deletions

File tree

packages/supabase_flutter/lib/src/passkey/passkey_options_mapper.dart

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ import 'package:passkeys_platform_interface/types/types.dart';
55
///
66
/// The Supabase API returns options in the W3C
77
/// `PublicKeyCredentialCreationOptionsJSON` format, which already uses the same
8-
/// field names as [RegisterRequestType.fromJson]. The adjustments needed are
9-
/// stripping base64url padding from the challenge and credential ids (the
10-
/// plugin rejects padded values), ensuring every excluded credential carries
11-
/// a `transports` list (the plugin requires it), and backfilling
12-
/// `authenticatorSelection.requireResidentKey` (the plugin requires it, but
13-
/// the WebAuthn spec has treated it as optional since Level 2, so the server
14-
/// may omit it).
8+
/// field names as [RegisterRequestType.fromJson]. The only adjustments needed
9+
/// are stripping base64url padding from the challenge and credential ids (the
10+
/// plugin rejects padded values) and ensuring every excluded credential carries
11+
/// a `transports` list (the plugin requires it).
1512
RegisterRequestType passkeyRegisterRequestFromOptions(
1613
Map<String, dynamic> options,
1714
) {
@@ -27,13 +24,6 @@ RegisterRequestType passkeyRegisterRequestFromOptions(
2724
json['excludeCredentials'] = _normalizeCredentials(excludeCredentials);
2825
}
2926

30-
final authenticatorSelection = json['authenticatorSelection'];
31-
if (authenticatorSelection is Map) {
32-
json['authenticatorSelection'] = _normalizeAuthenticatorSelection(
33-
authenticatorSelection,
34-
);
35-
}
36-
3727
return RegisterRequestType.fromJson(json);
3828
}
3929

@@ -81,21 +71,6 @@ List<Map<String, dynamic>> _normalizeCredentials(List<dynamic> credentials) {
8171
}).toList();
8272
}
8373

84-
/// Backfills `requireResidentKey` when the server omits it, deriving it from
85-
/// `residentKey` per the WebAuthn spec's backwards compatibility guidance:
86-
/// `true` if `residentKey` is `"required"`, `false` otherwise.
87-
Map<String, dynamic> _normalizeAuthenticatorSelection(
88-
Map<dynamic, dynamic> authenticatorSelection,
89-
) {
90-
final normalized = Map<String, dynamic>.from(authenticatorSelection);
91-
92-
if (normalized['requireResidentKey'] is! bool) {
93-
normalized['requireResidentKey'] = normalized['residentKey'] == 'required';
94-
}
95-
96-
return normalized;
97-
}
98-
9974
String _stripBase64UrlPadding(String value) {
10075
var end = value.length;
10176
while (end > 0 && value[end - 1] == '=') {

packages/supabase_flutter/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ dependencies:
1616
sdk: flutter
1717
http: ^1.2.2
1818
meta: ^1.7.0
19-
passkeys_platform_interface: ^2.7.0
19+
passkeys_platform_interface: ^2.8.0
2020
supabase: 2.13.3
2121
url_launcher: ^6.1.2
2222
shared_preferences: ^2.0.0

packages/supabase_flutter/test/passkey_options_mapper_test.dart

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -66,49 +66,6 @@ void main() {
6666
['internal', 'hybrid'],
6767
);
6868
});
69-
70-
test(
71-
'defaults missing requireResidentKey to false when residentKey is not required',
72-
() {
73-
final options = baseOptions()
74-
..['authenticatorSelection'] = {
75-
'residentKey': 'preferred',
76-
'userVerification': 'preferred',
77-
};
78-
79-
final request = passkeyRegisterRequestFromOptions(options);
80-
81-
expect(request.authSelectionType?.requireResidentKey, false);
82-
},
83-
);
84-
85-
test(
86-
'derives missing requireResidentKey from a required residentKey',
87-
() {
88-
final options = baseOptions()
89-
..['authenticatorSelection'] = {
90-
'residentKey': 'required',
91-
'userVerification': 'preferred',
92-
};
93-
94-
final request = passkeyRegisterRequestFromOptions(options);
95-
96-
expect(request.authSelectionType?.requireResidentKey, true);
97-
},
98-
);
99-
100-
test('keeps a provided requireResidentKey as is', () {
101-
final options = baseOptions()
102-
..['authenticatorSelection'] = {
103-
'residentKey': 'preferred',
104-
'requireResidentKey': true,
105-
'userVerification': 'preferred',
106-
};
107-
108-
final request = passkeyRegisterRequestFromOptions(options);
109-
110-
expect(request.authSelectionType?.requireResidentKey, true);
111-
});
11269
});
11370

11471
group('passkeyAuthenticateRequestFromOptions', () {

0 commit comments

Comments
 (0)