capacitor-community / capacitor-community/generic-oauth2
ERR_STATES_NOT_MATCH in Safari, works fine in Chrome
- 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
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