atinux / nuxt-auth-utils

Add Authentication to Nuxt applications with secured & sealed cookies sessions.
MIT License
974 stars 91 forks source link

Keycloak Auth failing in production on setUserSession call #117

Closed buff closed 3 months ago

buff commented 4 months ago

When I run the same build in production Heroku environment I can see the user gets redirected to keycloak... The user adds username/password credentials and is redirected back with success. The code calls the setUserSession and results in the stack trace below. The same code runs to the sendRedirect section of the code in my local development environment. Have I configured something incorrectly that is required for production? 2024-07-08T10:45:05.747311+00:00 app[web.1]: [nuxt] [request error] [unhandled] [500] Empty password 2024-07-08T10:45:05.747327+00:00 app[web.1]: at seal (./.output/server/chunks/runtime.mjs:1664:11) 2024-07-08T10:45:05.747328+00:00 app[web.1]: at sealSession (./.output/server/chunks/runtime.mjs:3532:24) 2024-07-08T10:45:05.747329+00:00 app[web.1]: at updateSession (./.output/server/chunks/runtime.mjs:3520:26) 2024-07-08T10:45:05.747329+00:00 app[web.1]: at getSession (./.output/server/chunks/runtime.mjs:3506:11) 2024-07-08T10:45:05.747330+00:00 app[web.1]: at useSession (./.output/server/chunks/runtime.mjs:3448:9) 2024-07-08T10:45:05.747330+00:00 app[web.1]: at _useSession (./.output/server/chunks/runtime.mjs:6634:10) 2024-07-08T10:45:05.747330+00:00 app[web.1]: at setUserSession (./.output/server/chunks/runtime.mjs:6609:25) 2024-07-08T10:45:05.747330+00:00 app[web.1]: at onSuccess (./.output/server/chunks/routes/auth/keycloak.get.mjs:1048:11)

sewalsh commented 4 months ago

This is because you're missing the process.env.NUXT_SESSION_PASSWORD environment variable.

buff commented 3 months ago

This is because you're missing the process.env.NUXT_SESSION_PASSWORD environment variable.

@sewalsh No, it is there. I have looked at this some more and it seems to be related to redirecting on heroku. Why would you think it has something to do with the session password? That raises an error does it not? It returns everything correctly but the protocol. The server function getRequestURL that is used to create the redirect returns the wrong protocol. This is rejected by keycloak because it does not match the expected redirect URL

atinux commented 3 months ago

I see, this is quite tricky when there is a proxy behind as I suppose that the Heroku server is HTTP and they have their reverse proxy adding HTTPS, making the Nuxt server not capable of knowing the right protocol.

What you can do is to overwrite the redirect_uri @buff in production (see https://github.com/Atinux/nuxt-auth-utils/blob/633c0047a2b8bd5f44d5ca7f638176232c8c9b8c/src/runtime/server/lib/oauth/keycloak.ts#L104):

export default oauthKeycloakEventHandler({
  config: {
    authorizationParams: import.meta.dev
      ? {}
      : {
          redirect_uri: 'https://my-prod-website.com/auth/keycloak',
        },
  },
  async onSuccess(event, { user }) {
   // ...
  },
})
buff commented 3 months ago

@Atinux This issue is only partly fixed... The intitial redirect to keycloak is handled correctly but the token retrieval is still using the redirect from the server function const redirectUrl = getRequestURL(event).href; The body of that api call is: body: new URLSearchParams({ client_id: config.clientId, client_secret: config.clientSecret, grant_type: "authorization_code", redirect_uri: parsePath(redirectUrl).pathname, code }).toString() This results in an incorrect redirect_uri error because keycloak compares the full URL

atinux commented 3 months ago

I guess we could then add a config.redirectUrl option that can overwrite it here if provided (https://github.com/Atinux/nuxt-auth-utils/blob/main/src/runtime/server/lib/oauth/keycloak.ts#L91)

const redirectUrl = config.redirectUrl || getRequestURL(event).href

Would that work for you? If so, happy to open a PR for it?

buff commented 3 months ago

I guess we could then add a config.redirectUrl option that can overwrite it here if provided (https://github.com/Atinux/nuxt-auth-utils/blob/main/src/runtime/server/lib/oauth/keycloak.ts#L91)

const redirectUrl = config.redirectUrl || getRequestURL(event).href

Would that work for you? If so, happy to open a PR for it?

Yes... I think it would be cleaner to change the one redirectUrl parameter and remove the spread ...config.authorizationParams. Not sure if you had other intentions for that... The problem I think stems from the use of parsePath(redirectUrl).pathname... this will omit the server and protocol. The auth server checks for the full URL. Not sure about this last point. It is what I keep running into when trying to investigate the issue. It might be the case for more than just keycloak that requires that the full URL match