Skip to content

Commit 03235ee

Browse files
committed
feat: add expo-crypto dependency and integrate randomUUID for nonce generation in useAppleSignIn hook
- Added expo-crypto as a dependency in package.json. - Updated useAppleSignIn hook to use Crypto.randomUUID() for generating a cryptographically secure nonce instead of Math.random(). - Mocked expo-crypto in useAppleSignIn tests to return a fixed UUID for consistent testing. - Updated tests to verify that randomUUID is called and the correct nonce is used in the sign-in flow.
1 parent a3d83bd commit 03235ee

File tree

4 files changed

+76
-50
lines changed

4 files changed

+76
-50
lines changed

packages/expo/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"@types/base-64": "^1.0.2",
9797
"expo-apple-authentication": "^7.2.4",
9898
"expo-auth-session": "^5.4.0",
99+
"expo-crypto": "^15.0.7",
99100
"expo-local-authentication": "^13.8.0",
100101
"expo-secure-store": "^12.8.1",
101102
"expo-web-browser": "^12.8.2",
@@ -105,6 +106,7 @@
105106
"@clerk/expo-passkeys": ">=0.0.6",
106107
"expo-apple-authentication": ">=7.0.0",
107108
"expo-auth-session": ">=5",
109+
"expo-crypto": ">=12",
108110
"expo-local-authentication": ">=13.5.0",
109111
"expo-secure-store": ">=12.4.0",
110112
"expo-web-browser": ">=12.5.0",

packages/expo/src/hooks/__tests__/useAppleSignIn.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const mocks = vi.hoisted(() => {
99
useSignUp: vi.fn(),
1010
signInAsync: vi.fn(),
1111
isAvailableAsync: vi.fn(),
12+
randomUUID: vi.fn(),
1213
};
1314
});
1415

@@ -30,6 +31,12 @@ vi.mock('expo-apple-authentication', () => {
3031
};
3132
});
3233

34+
vi.mock('expo-crypto', () => {
35+
return {
36+
randomUUID: mocks.randomUUID,
37+
};
38+
});
39+
3340
vi.mock('react-native', () => {
3441
return {
3542
Platform: {
@@ -69,6 +76,7 @@ describe('useAppleSignIn', () => {
6976
});
7077

7178
mocks.isAvailableAsync.mockResolvedValue(true);
79+
mocks.randomUUID.mockReturnValue('test-nonce-uuid');
7280
});
7381

7482
afterEach(() => {
@@ -98,10 +106,11 @@ describe('useAppleSignIn', () => {
98106
const response = await result.current.startAppleSignInFlow();
99107

100108
expect(mocks.isAvailableAsync).toHaveBeenCalled();
109+
expect(mocks.randomUUID).toHaveBeenCalled();
101110
expect(mocks.signInAsync).toHaveBeenCalledWith(
102111
expect.objectContaining({
103112
requestedScopes: expect.any(Array),
104-
nonce: expect.any(String),
113+
nonce: 'test-nonce-uuid',
105114
}),
106115
);
107116
expect(mockSignIn.create).toHaveBeenCalledWith({

packages/expo/src/hooks/useAppleSignIn.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useSignIn, useSignUp } from '@clerk/clerk-react';
22
import type { SetActive, SignInResource, SignUpResource, SignUpUnsafeMetadata } from '@clerk/types';
33
import * as AppleAuthentication from 'expo-apple-authentication';
4+
import * as Crypto from 'expo-crypto';
45
import { Platform } from 'react-native';
56

67
import { errorThrower } from '../utils/errors';
@@ -83,9 +84,8 @@ export function useAppleSignIn() {
8384
}
8485

8586
try {
86-
// Generate a nonce for the Apple Sign-In request (required by Clerk)
87-
// Note: Using Math.random() is acceptable here as the identity token is validated by Clerk's backend
88-
const nonce = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
87+
// Generate a cryptographically secure nonce for the Apple Sign-In request (required by Clerk)
88+
const nonce = Crypto.randomUUID();
8989

9090
// Request Apple authentication with requested scopes
9191
const credential = await AppleAuthentication.signInAsync({

0 commit comments

Comments
 (0)