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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SvelteKitAuth: signOut is not working when initiated via API call using /auth/signout #8134

Closed
aakash14goplani opened this issue Jul 25, 2023 · 4 comments
Labels
triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@aakash14goplani
Copy link

Environment

  System:
    OS: Windows 10 10.0.22621
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
    Memory: 5.34 GB / 15.41 GB
  Binaries:
    Node: 16.17.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 8.19.2 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.5.1 - ~\AppData\Local\pnpm\pnpm.CMD
  Browsers:
    Edge: Spartan (44.22621.1992.0), Chromium (115.0.1901.183)
    Internet Explorer: 11.0.22621.1

Reproduction URL

https://github.com/aakash14goplani/SvelteKitAuth-signOut-Bug

Describe the issue

  • signOut using API endpoint on server side is not working as expected for SvelteKitAuth package.
  • When we hit /auth/signout the request pass through but it does not invalidates session and session-token cookie still persist.
  • Client side signIn and signOut are working fine. Also /auth/signin i.e. signIn on server side works fine as well. It is just signOut part that is broken.

How to reproduce

  1. Clone this repo: https://github.com/aakash14goplani/SvelteKitAuth-signOut-Bug or go through live demo: https://svelte-kit-auth-sign-out-bug.vercel.app/
  2. The root page i.e. / deals with client side login and logout which works perfectly fine.
  3. The /login page deals with programmatic login using /auth/signin i.e. as soon as you land on this page, authentication process will trigger on its own. This also works fine.
  4. PROBLEM is in /logout page that deals with programmatic logout using /auth/signout i.e. as soon as you land on this page, you should get logged out but this does not happens. USer is still logged in and session-token cookie still persists! Also there are no visible errors in browser console or CLI.

Expected behavior

  • We should be able to invalidate user session using /auth/signout
@aakash14goplani aakash14goplani added the triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. label Jul 25, 2023
@ksmoore17
Copy link

I think I have seen the same issue with a keycloak provider. I believe that authentication was happening silently (without need to redirect to any kind of login form) because the actual oauth2 session (the source for the auth.js session/session cookie) is persisted by your provider.

The /auth/signout endpoint seems to only delete the auth.js session cookie. My best guess at what is happening: when trying to authenticate, SvelteKitAuth silently succeeds in getting the oauth2 session that I believe keycloak possibly associates with the ip (?). If there's a place in auth0 dashboard where you can manage active sessions, you may find that after hitting the /auth/signout endpoint, the session remains. I'm not sure if Auth0 works the same way as keycloak, or if we have the same issue, or if I have diagnosed the problem correctly, but what worked for me was to hit the oauth2 logout endpoint (found in well-known) with the id_token_hint before the /auth/signout endpoint (as you are doing in your logout/+page.server.ts) to invalidate the persisted oauth2 session.

async function logoutKeycloak(fetch: Fetch, idToken: string) {
	await fetch(keycloakLogoutUrl, {
		method: 'POST',
		headers: {
			'Content-Type': 'application/x-www-form-urlencoded'
		},
		body: new URLSearchParams({
			id_token_hint: idToken
		})
	});
}

The idToken comes from the initial token grant, and I'm storing it in the session (use jwt and session callbacks in SvelteKitAuth config).

@aakash14goplani
Copy link
Author

aakash14goplani commented Jul 26, 2023

@ksmoore17 - Thanks for reply. But why does things work out on client-side signOut() very well? Why do we have to do extra work while triggering /auth/signout? Shouldn't that be handled by @auth/core the way they handle things as client-side?

For client-side, in the file next-auth\packages\frameworks-sveltekit\src\lib\client.ts, they don't pass any special params yet the session gets invalidated and scenario works perfectly fine

/**
 * Signs the user out, by removing the session cookie.
 * Automatically adds the CSRF token to the request.
 *
 * [Documentation](https://authjs.dev/reference/sveltekit/client#signout)
 */
export async function signOut(options?: SignOutParams) {
  const { callbackUrl = window.location.href } = options ?? {}
  // TODO: Custom base path
  // TODO: Remove this since Sveltekit offers the CSRF protection via origin check
  const csrfTokenResponse = await fetch("/auth/csrf")
  const { csrfToken } = await csrfTokenResponse.json()
  const res = await fetch(`/auth/signout`, {
    method: "post",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "X-Auth-Return-Redirect": "1",
    },
    body: new URLSearchParams({
      csrfToken,
      callbackUrl,
    }),
  })
  const data = await res.json()

  const url = data.url ?? callbackUrl
  window.location.href = url
  // If url contains a hash, the browser does not reload the page. We reload manually
  if (url.includes("#")) window.location.reload()
}

If I do the same in my local in +page.server.ts things don't work, this is something that is confusing me alot!

@ksmoore17
Copy link

I hear you.. the server side handling that you and I have implemented (#7979) seems like a hack for some reason, I guess. Maybe something going on inside the /auth/signout endpoint that only works when accessed from client side for some reason. Perhaps it has something to do with the SvelteKitAuth not being triggered immediately after the client signOut call because window.location is client side routing (in other words when setting window.location, handle in hooks.server.ts does not trigger, so the session cookie is not immediately set again). I have to admit that I don't understand oauth2 or the auth.js internals very well. Have you tried the direct post to the oauth2 logout endpoint.. did that work?

@aakash14goplani
Copy link
Author

@ksmoore17 - that what I did i.e. direct post to OIDC endpoint and it worked. Thank you for detailed insights. I still believe core team should work on pin-pointing and focusing this bug as it is weird that things works on client side but not on server side!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

No branches or pull requests

2 participants