next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

FusionAuth - Handle www-authenticate challenges as needed

Open alex-fusionauth opened this issue 2 years ago • 13 comments
trafficstars

Provider type

FusionAuth

Environment

System: OS: macOS 13.4.1 CPU: (12) arm64 Apple M2 Pro Memory: 1.70 GB / 32.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 20.6.1 - /opt/homebrew/bin/node npm: 9.8.1 - /opt/homebrew/bin/npm pnpm: 8.7.6 - /opt/homebrew/bin/pnpm Browsers: Brave Browser: 117.1.58.129 Chrome: 117.0.5938.92 Safari: 16.5.1

"dependencies": { "@auth/core": "latest", "@auth/sveltekit": "latest" },

Reproduction URL

https://github.com/alex-fusionauth/fusionauth-sveltekit

Describe the issue

Trying to find why Auth.js is throwing TODO: Handle www-authenticate challenges as needed. It appears that in the package oauth4webapi the method parseWwwAuthenticateChallenges is called and brings back WWW-Authenticate header from the code grant response. This has scheme:'basic' listed which causes the error.

Origin of issue

    let challenges;
    if ((challenges = o.parseWwwAuthenticateChallenges(codeGrantResponse))) {
        for (const challenge of challenges) {
            console.log("challenge", challenge);
        }
        throw new Error("TODO: Handle www-authenticate challenges as needed");
    }

Should the user or FusionAuth be handling this somehow?

How to reproduce

You will need docker.

  1. run docker compose up -d
  2. cd complete-example
  3. copy .env.example to .env
  4. npm run dev
  5. click sing in button
  6. sign in using [email protected] with password: password
image

Chooose provider while signing in image

Error thrown: image

challenge { scheme: 'basic', parameters: {} }
[auth][error][CallbackRouteError]: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: Error: TODO: Handle www-authenticate challenges as needed
    at handleOAuth (file:///Users/afa/dev/inversoft/fusionauth/fusionauth-quickstart-javascript-sveltekit-web/complete-application/node_modules/@auth/sveltekit/node_modules/@auth/core/lib/oauth/callback.js:69:15)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Module.callback (file:///Users/afa/dev/inversoft/fusionauth/fusionauth-quickstart-javascript-sveltekit-web/complete-application/node_modules/@auth/sveltekit/node_modules/@auth/core/lib/routes/callback.js:20:41)
    at async AuthInternal (file:///Users/afa/dev/inversoft/fusionauth/fusionauth-quickstart-javascript-sveltekit-web/complete-application/node_modules/@auth/sveltekit/node_modules/@auth/core/lib/index.js:65:38)
    at async Proxy.Auth (file:///Users/afa/dev/inversoft/fusionauth/fusionauth-quickstart-javascript-sveltekit-web/complete-application/node_modules/@auth/sveltekit/node_modules/@auth/core/index.js:100:30)
    at async Module.respond (/Users/afa/dev/inversoft/fusionauth/fusionauth-quickstart-javascript-sveltekit-web/complete-application/node_modules/@sveltejs/kit/src/runtime/server/respond.js:282:20)
    at async file:///Users/afa/dev/inversoft/fusionauth/fusionauth-quickstart-javascript-sveltekit-web/complete-application/node_modules/@sveltejs/kit/src/exports/vite/dev/index.js:510:22
[auth][details]: {
  "provider": "fusionauth"
}

Expected behavior

There should be no error. Login should continue as the AuthToken is good.

alex-fusionauth avatar Sep 27 '23 21:09 alex-fusionauth

Just a note I am the DevRel at FusionAuth, happy to work through how to make this valid.

alex-fusionauth avatar Sep 27 '23 22:09 alex-fusionauth

I've been dealing with this Discord provider issue for, like, a whole day now. The weird thing is, when I use it, I don't even get an error message or anything. I just get sent to this http://localhost:3000/api/auth/error?error= page, and there are no errors in the URL or in my logs.

The crazy part is, when I deploy it on Vercel, it works perfectly fine. This situation seriously sucks! image

marckustech avatar Sep 28 '23 13:09 marckustech

This is a part that we haven't tacked in the core package. If you are willing to contribute a PR, I'm happy to take a look @alex-fusionauth . It would solve the issue not only for FusionAuth but for all auth providers which return WWWAuthenticateChallenge

ThangHuuVu avatar Oct 22 '23 06:10 ThangHuuVu

Tried to implement Auth.js with SvelteKit and got stuck here also. Any idea what to look for?

sohnemann avatar Nov 10 '23 00:11 sohnemann

Same here. I tried to implement Auth.js with SvelteKit using Okta and got stuck here also. How do we handle WWWAuthenticateChallenge?

hardylr avatar Nov 16 '23 10:11 hardylr

Hey @ThangHuuVu, I am also having the issue with the Notion provider fyi

dhadrien avatar Nov 30 '23 11:11 dhadrien

I managed to get Auth.js working with SvelteKit and Okta. Seems like you do not need to set a clientSecret when using Okta when setting token_endpoint_auth_method: "none". Hope this helps.

export const handle = SvelteKitAuth({
  providers: [
    Okta({
          clientId: OKTA_CLIENT_ID,
          //clientSecret: OKTA_CLIENT_SECRET, // DO NOT SET!
          //https://github.com/nextauthjs/next-auth/issues/3540#issuecomment-1021807328
          issuer: OKTA_ISSUER,
          checks: ["pkce", "state"],
          client: {
            token_endpoint_auth_method: "none",
          }          
        }) as Provider
  ]  
})

hardylr avatar Nov 30 '23 12:11 hardylr

Hi everyone!

Not sure if this would help anyone, but I resolved a careless mistake from my end for an error like the above (SvelteKit and Discord):

challenge {
  scheme: 'basic',
  parameters: { error: 'invalid_client', error_description: '' }
}
[auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: Error: TODO: Handle www-authenticate challenges as needed

The "invalid_client" error indicated that client secret was incorrect.

Cheers!

luis815 avatar Jan 11 '24 05:01 luis815

Hey everyone, running in this same exact issue no matter what I do. Is there any solution to this? I tried following this guide: https://fusionauth.io/docs/quickstarts/quickstart-javascript-nextjs-web#authentication and I'm getting

challenge { scheme: 'basic', parameters: {} } [auth][error][CallbackRouteError]: Read more at https://errors.authjs.dev#callbackrouteerror [auth][cause]: Error: TODO: Handle www-authenticate challenges as needed [auth][details]: { "provider": "fusionauth" }

I also tried setting token_endpoint_auth_method to "none" and "client_secret_basic", none of them worked sadly.

I also get an "Invalid URL" error when trying to configure the Provider as it's shown in the guide. Instead I have to provide the authorization and token endpoint manually:

authorization: `https://${env.FUSIONAUTH_ISSUER}/oauth2/authorize`,
token: `https://${env.FUSIONAUTH_ISSUER}/oauth2/token`,

I'm on 5.0.0-beta.2 of next-auth and 0.20.0 of @auth/core.

Thank you!

UlasCanAk avatar Jan 15 '24 15:01 UlasCanAk

Hey everyone, running in this same exact issue no matter what I do. Is there any solution to this? I tried following this guide: https://fusionauth.io/docs/quickstarts/quickstart-javascript-nextjs-web#authentication and I'm getting

challenge { scheme: 'basic', parameters: {} } [auth][error][CallbackRouteError]: Read more at https://errors.authjs.dev#callbackrouteerror [auth][cause]: Error: TODO: Handle www-authenticate challenges as needed [auth][details]: { "provider": "fusionauth" }

I also tried setting token_endpoint_auth_method to "none" and "client_secret_basic", none of them worked sadly.

I also get an "Invalid URL" error when trying to configure the Provider as it's shown in the guide. Instead I have to provide the authorization and token endpoint manually:

authorization: `https://${env.FUSIONAUTH_ISSUER}/oauth2/authorize`,
token: `https://${env.FUSIONAUTH_ISSUER}/oauth2/token`,

I'm on 5.0.0-beta.2 of next-auth and 0.20.0 of @auth/core.

Thank you!

@UlasCanAk This looks like it is a config issue within fusionauth, might be better to post on our community forum or if you ping me on our Slack I can help you directly https://fusionauth.io/community

alex-fusionauth avatar Jan 18 '24 20:01 alex-fusionauth

From my understanding, the WWW-Authenticate header should only be included in a 401 response and not with other statuses, as per the specification in the linked RFC.

I'm wondering why we'd have to include this in a 200 response. It would be great to get some clarification on this from @alex-fusionauth or any other FusionAuth devs.

In the meantime, I've provided a solution (FusionAuth provider with config for v5 next-auth@beta) to remove the header from within the response. This should help avoid the challenge exception users have been having in this thread, and allow the rest of the auth process to proceed smoothly:

Fusionauth({
      clientId: process.env.FUSIONAUTH_CLIENT_ID,
      clientSecret: process.env.FUSIONAUTH_CLIENT_SECRET,
      tenantId: process.env.FUSIONAUTH_TENANT_ID,
      issuer: process.env.FUSIONAUTH_ISSUER,
      userinfo: process.env.FUSIONAUTH_OAUTH_USERINFO_ENDPOINT,
      authorization: {
        url: process.env.FUSIONAUTH_OAUTH_AUTHORIZE_ENDPOINT,
        params: {
          scope: "offline_access",
        },
      },
      token: {
        url: process.env.FUSIONAUTH_OAUTH_TOKEN_ENDPOINT,
        conform: async (response: Response) => {
          if (response.status === 401) return response;

          const newHeaders = Array.from(response.headers.entries())
            .filter(([key]) => key.toLowerCase() !== "www-authenticate")
            .reduce((headers, [key, value]) => (headers.append(key, value), headers), new Headers());

          return new Response(response.body, {
            status: response.status,
            statusText: response.statusText,
            headers: newHeaders,
          });
        },
      },
    }),

firebotQL avatar Jan 24 '24 10:01 firebotQL

Thanks @firebotQL - I can speak on behalf of FusionAuth.

In section 4.1 of RFC 7235 where it describes that when a 401 is returned this header must be added, it also says the server may respond with this header for other responses. It isn't explicit, but this sounds like it is ok to return this header on a 200 as well.

A server MAY generate a WWW-Authenticate header field in other response messages to indicate that supplying credentials (or different credentials) might affect the response.

  • https://datatracker.ietf.org/doc/html/rfc7235#section-4.1

My guess is that is why we are always returning it. This statement in the RFC isn't exactly crystal clear if "other response messages" means other response codes than 401 or something else. If I have the correct understanding (I may not) of "other messages", would it be safe to ignore this header unless the status code is also a 401?

I will do some additional research, and we can revisit our current behavior to see if there was any historical reason to always write this header, or if we just made an assumption that it was ok to always return it.

Thank you for adding this work around while we investigate further! Much appreciated.

I opened this issue in FusionAuth to investigate and track as well.

  • https://github.com/FusionAuth/fusionauth-issues/issues/2645

robotdan avatar Feb 07 '24 20:02 robotdan

I have added a new Issue/PR to update FusionAuth defaults to better represent our needs. Users should be able to override as they see fit. We can back out the token.conform once it is merged into the core release.

Issue: https://github.com/nextauthjs/next-auth/issues/10867 PR: https://github.com/nextauthjs/next-auth/issues/10868

alex-fusionauth avatar May 09 '24 20:05 alex-fusionauth