capacitor-community / capacitor-community/generic-oauth2

ERR_STATES_NOT_MATCH in Safari, works fine in Chrome

Open
#280 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
281
Forks
129
PR merge metrics
No merged PRs in 30d

Description

**Description**

I am experiencing an issue with the OAuth2 flow in my application when using Safari. The state parameter validation fails, resulting in an ERR_STATES_NOT_MATCH error, while the same flow works perfectly in Chrome.

**Environment**

Browser: Safari
Version: 17.6
Operating System: Apple Macbook Air M1 (2020) Sonoma

**Steps to Reproduce**

1. Open the application in Safari.
2. Initiate the OAuth2 login flow.
3. Complete the login process.
4. Observe the redirection back to the application.

**Expected Behavior**

The application should redirect back successfully and match the state parameter without any errors.

**Actual Behavior**

The application fails to match the state parameter, resulting in an ERR_STATES_NOT_MATCH error.

**Logs**

Here are some logs that may help in diagnosing the issue:

`[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (undefined, line 0)
[Error] [ERROR]: Error: Not Found
error (logger.utility.tsx:12)
(anonymous function) (splash.tsx:302)
[Log] I/Capacitor/GenericOAuth2Plugin: Authorization url: https://keycloak.iqzsystems.io/realms/dev/protocol/openid-connect/auth?client_id=dev-connect&response_type=code&redirect_uri=http://localhost:3000/splash&scope=email%profilenullffline_access&state=041NwVx5C36ZfOK5uVsx&code_challenge=rPVfWjNP4SvkMP5J0JzXhw1J-BMLYUV4RlMYchvY25Y&code_challenge_method=S256 (web-SHD4VUV7.js, line 456)
[Log] I/Capacitor/GenericOAuth2Plugin: Url from Provider: http://localhost:3000/splash?state=xkwut2OHRylPJHtY0thx&session_state=8acd5b58-a701-45bd-a1cb-ef9916dae562&code=4525f4cc-66a1-4c88-8a14-6c8c5091658f.8acd5b58-a701…ef9916dae562.d65c09d0-e10b-4417-816e-88bc723a407f# – null (web-SHD4VUV7.js, line 456)
[Log] I/Capacitor/GenericOAuth2Plugin: Authorization response: – {state: "xkwut2OHRylPJHtY0thx", session_state: "8acd5b58-a701-45bd-a1cb-ef9916dae562", code: "4525f4cc-66a1-4c88-8a14-6c8c5091658f.8acd5b58-a701…ef9916dae562.d65c09d0-e10b-4417-816e-88bc723a407f"} (web-SHD4VUV7.js, line 456)
{state: "xkwut2OHRylPJHtY0thx", session_state: "8acd5b58-a701-45bd-a1cb-ef9916dae562", code: "4525f4cc-66a1-4c88-8a14-6c8c5091658f.8acd5b58-a701…ef9916dae562.d65c09d0-e10b-4417-816e-88bc723a407f"}Object
[Log] I/Capacitor/GenericOAuth2Plugin: State from web options: 041NwVx5C36ZfOK5uVsx – null (web-SHD4VUV7.js, line 456)
[Log] I/Capacitor/GenericOAuth2Plugin: State returned from provider: xkwut2OHRylPJHtY0thx – null (web-SHD4VUV7.js, line 456)`

**Additional Information**

1. The same code and flow work perfectly in Chrome without any issues.
2. I have checked the storage and state parameter handling, and it seems to be implemented correctly.
3. Any guidance or help in resolving this issue would be greatly appreciated.

`import {
OAuth2AuthenticateOptions,
OAuth2RefreshTokenOptions,
} from '@capacitor-community/generic-oauth2';

export const OAuth2Options: OAuth2AuthenticateOptions = {
appId: `${import.meta.env.VITE_CLIENT_ID}`,
scope: 'email profile offline_access',
authorizationBaseUrl: `https://${import.meta.env.VITE_KEYCLOCK_BASE_URL}/realms/${import.meta.env.VITE_REALM}/protocol/openid-connect/auth`,
accessTokenEndpoint: `https://${import.meta.env.VITE_KEYCLOCK_BASE_URL}/realms/${import.meta.env.VITE_REALM}/protocol/openid-connect/token`,
responseType: 'code',
web: {
appId: `${import.meta.env.VITE_CLIENT_ID}`,
redirectUrl: `${import.meta.env.VITE_REDIRECT_URL}`,
windowOptions: 'height=600,left=0,top=0',
accessTokenEndpoint: `https://${import.meta.env.VITE_KEYCLOCK_BASE_URL}/realms/${import.meta.env.VITE_REALM}/protocol/openid-connect/token`,
pkceEnabled: false,
responseType: 'code',
windowTarget: '_self',
},
android: {
appId: `${import.meta.env.VITE_CLIENT_ID}`,
responseType: 'code',
redirectUrl: '', // package name from google dev console
},
ios: {
appId: `${import.meta.env.VITE_CLIENT_ID}`,
responseType: 'code',
redirectUrl: '', // Bundle ID from google dev console
},
};

export const OAuth2RefreshOptions: OAuth2RefreshTokenOptions = {
appId: `${import.meta.env.VITE_CLIENT_ID}`,
accessTokenEndpoint: `https://${import.meta.env.VITE_KEYCLOCK_BASE_URL}/realms/${import.meta.env.VITE_REALM}/protocol/openid-connect/token`,
refreshToken: '',
};
`

Contributor guide

Open the contributing guide

Research direction

Start with the OAuth2 flow around splash.tsx and the GenericOAuth2Plugin logs, then inspect logger.utility.tsx for the reported error path. Compare the state sent in the authorization URL with the state returned by the provider in Safari; done means the redirect completes without ERR_STATES_NOT_MATCH.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
authentication, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.