Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Inconsistent NextAuth cookie state #7262

Open
1 of 3 tasks
Alarson93 opened this issue Feb 15, 2024 · 1 comment
Open
1 of 3 tasks

[Bug]: Inconsistent NextAuth cookie state #7262

Alarson93 opened this issue Feb 15, 2024 · 1 comment
Labels

Comments

@Alarson93
Copy link

Alarson93 commented Feb 15, 2024

Capacitor Version

馃拪   Capacitor Doctor  馃拪 

Latest Dependencies:

  @capacitor/cli: 5.7.0
  @capacitor/core: 5.7.0
  @capacitor/android: 5.7.0
  @capacitor/ios: 5.7.0

Installed Dependencies:

  @capacitor/cli: 5.7.0
  @capacitor/core: 5.7.0
  @capacitor/android: 5.7.0
  @capacitor/ios: 5.7.0

[success] iOS looking great! 馃憣
[error] index.html file is missing in /Users/myuser/repos/capacitor-poc/android/app/src/main/assets/public

Other API Details

npm version: 9.8.0
node version: 20.5.1
pod version: 1.12.1
next version: 13.3.4
next-auth version: 4.23.2
iOS version: 17.2.1

Platforms Affected

  • iOS
  • Android
  • Web

Current Behavior

We have a NextJS project that is authenticating with Keycloak via the NextAuth library. Web browsers and the Android Capacitor app work without issue, but we are experiencing "sticky" auth state in our iOS Capacitor app.

Here are a few examples (but there are many other permutations):

  1. Sign in -> close and reopen the app -> now in a signed out state
  2. Sign in -> refresh the app's web view using Safari Dev tools -> now in a signed out state
  3. Sign in -> close and reopen the app -> still signed in -> sign out -> briefly in a signed out state, but the pages reloads and we are signed in again (at least until our auth token expires)
  4. Sign in -> see the landing page in a signed in state -> sign out -> briefly in a signed out state, but the pages reloads and we are signed in again (at least until our auth token expires)

However, sometimes sign in / sign out works without issue. That is to say, the issue is sporadic, but:

  1. It seems to occur more on WiFi than wired connections.
  2. It happens on simulators and physical devices.
  3. It happens on local builds and TestFlight builds.

Turning off the iOS cookies plugin makes the issue go away. I created a WKHTTPCookieStore watcher that logs changes of our auth cookie. With the plugin disabled, I can see the cookie get created at sign in and removed at sign out. With the plugin enabled, I can see the cookie get created at sign in, removed at sign out, but re-added shortly after removal.

It seems that syncCookiesToWebView in CapacitorCookieManager is causing the cookie to be re-added. For example - HTTPCookieStorage may still have the auth cookie after logout, so triggering this function causes it to be added to WKHTTPCookieStore (which had already correctly removed it).

Expected Behavior

I expect the Capacitor app to respect the cookie state as set (or cleared) by the NextAuth library. Signing in should result in a consistent signed in state, both within the same app session and between sessions. Signing out should result in a consistent signed out state, both within the same app session and between sessions.

Project Reproduction

N/A

Additional Information

  • I'm not sure that I can quickly throw together an example project because this involves authentication services.
  • The NextAuth library is managing the cookie for us (i.e. we are not adding and removing it with CapacitorCookies.setCookie or CapacitorCookies.deleteCookie).
  • When the cookies plugin is enabled, I do not see the auth cookie go through CapacitorCookieManager.setCookie. We have another cookie for managing our hamburger menu and, when its state changes, I do see it go through CapacitorCookieManager.setCookie. So... I'm not sure why some cookies go through setCookie but others don't.
@Alarson93
Copy link
Author

Alarson93 commented Feb 16, 2024

Ok - did even more digging and have some interesting takeaways.

iOS cookie behavior:
It seems that WKWebView will set cookies that have a max age to WKHTTPCookieStore. A few seconds later, the cookie will also be set to HTTPCookieStorage. Deleting the cookie will remove it from WKHTTPCookieStore, but not from HTTPCookieStorage until the app has been killed and reopened.

This behavior was observed using a sample repo I created. The repo contains two basic projects:

  1. An iOS project that contains a WKWebView and cookie watchers.
  2. A NextJS project that has create cookie and destroy cookie buttons.

I have only observed this behavior on a physical device, so you must point the web view to your machines local IP address. Cookie events are logged to the Xcode console.

Here are the practical implications:
Let's say I have a project with Capacitor Cookies turned on. The project points to a web portal that authenticates with NextAuth.

Upon logging in, a new auth cookie is added to WKHTTPCookieStore. This new cookie does not trigger CapacitorCookieManager.setCookie for some reason, but that fine because the operating system(?) will add it to HTTPCookieStorage a few seconds later.

I am then brought back to landing screen which creates another cookie for managing my hamburger menu state (i.e. open or closed). This does trigger CapacitorCookieManager.setCookie, so the cookie is added to HTTPCookieStorage and then HTTPCookieStorage is synced to WKHTTPCookieStore. Everything still seems to be fine.

I now log out. The auth cookie is removed from WKHTTPCookieStore, but not immediately from HTTPCookieStorage. I am brought back to the landing page, thus updating the hamburger menu cookie and triggering CapacitorCookieManager.setCookie, so auth cookie HTTPCookieStorage is synced to HTTPCookieStorage to WKHTTPCookieStore. I am stuck in a logged in state.

If I leave the Capacitor Cookies plugin disabled, the syncing never happens so I am never stuck logged in.

Questions:

  • It seems like the Capacitor Cookies plugin is meant to keep WKHTTPCookieStore and HTTPCookieStorage in sync in a timely manner. Is that correct?
  • Should all cookies be intercepted by CapacitorCookieManager or are there certain types of cookies that cannot be intercepted?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant