Skip to content

Commit 369dcc2

Browse files
authored
fix(auth): Validate uuid params in admin methods (#1171)
1 parent 9ccd890 commit 369dcc2

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

packages/gotrue/lib/src/gotrue_admin_api.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:gotrue/gotrue.dart';
22
import 'package:gotrue/src/fetch.dart';
3+
import 'package:gotrue/src/helper.dart';
34
import 'package:gotrue/src/types/auth_response.dart';
45
import 'package:gotrue/src/types/fetch_options.dart';
56
import 'package:http/http.dart';
@@ -70,6 +71,7 @@ class GoTrueAdminApi {
7071
///
7172
/// This function should only be called on a server. Never expose your `service_role` key on the client.
7273
Future<void> deleteUser(String id) async {
74+
validateUuid(id);
7375
final options = GotrueRequestOptions(headers: _headers);
7476
await _fetch.request(
7577
'$_url/admin/users/$id',
@@ -173,6 +175,7 @@ class GoTrueAdminApi {
173175

174176
/// Gets the user by their id.
175177
Future<UserResponse> getUserById(String uid) async {
178+
validateUuid(uid);
176179
final options = GotrueRequestOptions(headers: _headers);
177180
final response = await _fetch.request(
178181
'$_url/admin/users/$uid',
@@ -187,6 +190,7 @@ class GoTrueAdminApi {
187190
String uid, {
188191
required AdminUserAttributes attributes,
189192
}) async {
193+
validateUuid(uid);
190194
final body = attributes.toJson();
191195
final options = GotrueRequestOptions(headers: _headers, body: body);
192196
final response = await _fetch.request(

packages/gotrue/lib/src/gotrue_admin_mfa_api.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'fetch.dart';
2+
import 'helper.dart';
23
import 'types/fetch_options.dart';
34
import 'types/mfa.dart';
45

@@ -17,6 +18,8 @@ class GoTrueAdminMFAApi {
1718

1819
Future<AuthMFAAdminListFactorsResponse> listFactors(
1920
{required String userId}) async {
21+
validateUuid(userId);
22+
2023
final data = await _fetch.request(
2124
'$_url/admin/users/$userId/factors',
2225
RequestMethodType.get,
@@ -33,6 +36,9 @@ class GoTrueAdminMFAApi {
3336
required String userId,
3437
required String factorId,
3538
}) async {
39+
validateUuid(userId);
40+
validateUuid(factorId);
41+
3642
final data = await _fetch.request(
3743
'$_url/admin/users/$userId/factors/$factorId',
3844
RequestMethodType.delete,

packages/gotrue/lib/src/helper.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,12 @@ String generatePKCEChallenge(String verifier) {
2121
return base64UrlEncode(sha256.convert(ascii.encode(verifier)).bytes)
2222
.split('=')[0];
2323
}
24+
25+
final uuidRegex =
26+
RegExp(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$');
27+
28+
void validateUuid(String id) {
29+
if (!uuidRegex.hasMatch(id)) {
30+
throw ArgumentError('Invalid id: $id, must be a valid UUID');
31+
}
32+
}

packages/gotrue/test/admin_test.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,40 @@ void main() {
111111
expect(userLengthBefore - 1, userLengthAfter);
112112
});
113113
});
114+
115+
group('validates ids', () {
116+
test('deleteUser() validates ids', () {
117+
expect(() => client.admin.deleteUser('invalid-id'),
118+
throwsA(isA<ArgumentError>()));
119+
});
120+
121+
test('getUserById() validates ids', () {
122+
expect(() => client.admin.getUserById('invalid-id'),
123+
throwsA(isA<ArgumentError>()));
124+
});
125+
126+
test('updateUserById() validates ids', () {
127+
expect(
128+
() => client.admin.updateUserById('invalid-id',
129+
attributes: AdminUserAttributes(email: 'test@test.com')),
130+
throwsA(isA<ArgumentError>()));
131+
});
132+
133+
test('listFactors() validates ids', () {
134+
expect(() => client.admin.mfa.listFactors(userId: 'invalid-id'),
135+
throwsA(isA<ArgumentError>()));
136+
});
137+
138+
test('deleteFactor() validates ids', () {
139+
expect(
140+
() => client.admin.mfa.deleteFactor(
141+
userId: 'invalid-id', factorId: 'invalid-factor-id'),
142+
throwsA(isA<ArgumentError>()));
143+
144+
expect(
145+
() => client.admin.mfa
146+
.deleteFactor(userId: userId1, factorId: 'invalid-factor-id'),
147+
throwsA(isA<ArgumentError>()));
148+
});
149+
});
114150
}

0 commit comments

Comments
 (0)