From 37ad5647f8cfe5f573e21ed15b1837b64790a4e6 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:05:12 +0530 Subject: [PATCH] ref: Simkl authentication to use PKCE and update exchangeCodeForToken method --- src/screens/SimklSettingsScreen.tsx | 15 +++++++++------ src/services/simklService.ts | 7 ++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/screens/SimklSettingsScreen.tsx b/src/screens/SimklSettingsScreen.tsx index 5bcb8087..3d1529fb 100644 --- a/src/screens/SimklSettingsScreen.tsx +++ b/src/screens/SimklSettingsScreen.tsx @@ -27,7 +27,6 @@ const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0; // Simkl configuration const SIMKL_CLIENT_ID = process.env.EXPO_PUBLIC_SIMKL_CLIENT_ID as string; -const SIMKL_REDIRECT_URI = process.env.EXPO_PUBLIC_SIMKL_REDIRECT_URI || 'nuvio://auth/simkl'; const discovery = { authorizationEndpoint: 'https://simkl.com/oauth/authorize', @@ -76,9 +75,10 @@ const SimklSettingsScreen: React.FC = () => { { clientId: SIMKL_CLIENT_ID, scopes: [], // Simkl doesn't strictly use scopes for basic access - redirectUri: SIMKL_REDIRECT_URI, // Must match what is set in Simkl Dashboard + redirectUri: redirectUri, responseType: ResponseType.Code, - // codeChallengeMethod: CodeChallengeMethod.S256, // Simkl might not verify PKCE, but standard compliant + usePKCE: true, + codeChallengeMethod: CodeChallengeMethod.S256, }, discovery ); @@ -90,12 +90,12 @@ const SimklSettingsScreen: React.FC = () => { // Handle the response from the auth request useEffect(() => { if (response) { - if (response.type === 'success') { + if (response.type === 'success' && request?.codeVerifier) { const { code } = response.params; setIsExchangingCode(true); logger.log('[SimklSettingsScreen] Auth code received, exchanging...'); - simklService.exchangeCodeForToken(code) + simklService.exchangeCodeForToken(code, request.codeVerifier) .then(success => { if (success) { refreshAuthStatus(); @@ -109,11 +109,14 @@ const SimklSettingsScreen: React.FC = () => { openAlert(t('common.error'), t('simkl.auth_error_generic')); }) .finally(() => setIsExchangingCode(false)); + } else if (response.type === 'success') { + logger.error('[SimklSettingsScreen] Missing PKCE code verifier on successful auth response'); + openAlert(t('common.error'), t('simkl.auth_error_msg')); } else if (response.type === 'error') { openAlert(t('simkl.auth_error_title'), t('simkl.auth_error_generic') + ' ' + (response.error?.message || t('common.unknown'))); } } - }, [response, refreshAuthStatus]); + }, [response, refreshAuthStatus, request?.codeVerifier, t]); const handleSignIn = () => { if (!SIMKL_CLIENT_ID) { diff --git a/src/services/simklService.ts b/src/services/simklService.ts index ef027ffe..ef0d4db7 100644 --- a/src/services/simklService.ts +++ b/src/services/simklService.ts @@ -301,7 +301,7 @@ export class SimklService { * Exchange code for access token * Simkl tokens do not expire */ - public async exchangeCodeForToken(code: string): Promise { + public async exchangeCodeForToken(code: string, codeVerifier: string): Promise { await this.ensureInitialized(); try { @@ -315,7 +315,8 @@ export class SimklService { client_id: SIMKL_CLIENT_ID, client_secret: SIMKL_CLIENT_SECRET, redirect_uri: SIMKL_REDIRECT_URI, - grant_type: 'authorization_code' + grant_type: 'authorization_code', + code_verifier: codeVerifier }) }); @@ -937,4 +938,4 @@ export class SimklService { return null; } } -} \ No newline at end of file +}