nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
24.1k stars 3.34k forks source link

Azure B2C Custom provider fails when using authorization code flow #7810

Open nmowatt opened 1 year ago

nmowatt commented 1 year ago

Provider type

Custom provider

Environment

  System:
    OS: macOS 12.6
    CPU: (10) arm64 Apple M1 Max
    Memory: 995.92 MB / 64.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.16.0 - ~/.nvm/versions/node/v18.16.0/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.5.1 - ~/.nvm/versions/node/v18.16.0/bin/npm
  Browsers:
    Chrome: 114.0.5735.133
    Safari: 15.6.1

Reproduction URL

Client project. Using Svelte.

Describe the issue

I'm using custom provider to get Azure B2C working. I have another issue related to Azure B2C failing with SvelteKitAuth (https://github.com/nextauthjs/next-auth/issues/7809).

When I'm using Implicit flow (which returns both and access_token and an id_token) it works fine, but whenever I try to use authorization code flow, which is the recommended way, the signin fails with error:

[auth][error][CallbackRouteError]: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: OperationProcessingError: "response" body "access_token" property must be a non-empty string
    at processGenericAccessTokenResponse (file:///<LOCAL_PATH>/node_modules/oauth4webapi/build/index.js:892:15)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Module.processAuthorizationCodeOAuth2Response (file:///<LOCAL_PATH>/node_modules/oauth4webapi/build/index.js:1054:20)
    at async handleOAuth (file:///<LOCAL_PATH>/node_modules/@auth/sveltekit/node_modules/@auth/core/lib/oauth/callback.js:88:18)
    at async Module.callback (file:///<LOCAL_PATH>/node_modules/@auth/sveltekit/node_modules/@auth/core/lib/routes/callback.js:14:41)
    at async AuthInternal (file:///<LOCAL_PATH>/node_modules/@auth/sveltekit/node_modules/@auth/core/lib/index.js:64:38)
    at async Proxy.Auth (file:///<LOCAL_PATH>/node_modules/@auth/sveltekit/node_modules/@auth/core/index.js:100:30)
    at async Module.respond (/<LOCAL_PATH>/node_modules/@sveltejs/kit/src/runtime/server/respond.js:274:20)
    at async file:///<LOCAL_PATH>/node_modules/@sveltejs/kit/src/exports/vite/dev/index.js:505:22
[auth][details]: {
  "provider": "b2c"
}

Here is my code:

import { SvelteKitAuth } from "@auth/sveltekit"
import { B2C_TENANT, B2C_TENANT_ID, B2C_POLICY, B2C_SCOPES, B2C_CLIENT_ID, B2C_CLIENT_SECRET, AUTH_SECRET } from '$env/static/private';

export const handle = SvelteKitAuth({
  providers: [
    {
      id: "b2c",
      name: "B2C",
      type: "oauth",
      wellKnown: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/v2.0/.well-known/openid-configuration`,
      authorization: {
        url: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/oauth2/v2.0/authorize`,
        params: {
          scope: B2C_SCOPES
        }
      },
      token: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/oauth2/v2.0/token`,
      userinfo: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/oauth2/v2.0/userinfo`,
      issuer: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT_ID}/v2.0/`,
      clientId: B2C_CLIENT_ID,
      clientSecret: B2C_CLIENT_SECRET
    } as any
  ],
  secret: AUTH_SECRET,
});

I've also tried setting the type to "oidc" since that's what the AzureADB2C provider is using, but I guess I would want oauth here (?)

So I could check Access tokens (used for implicit flows) here, but that is not the recommended way to obtain access tokens anymore.

image

How to reproduce

  1. Define a custom provider as above.
  2. Click signIn('b2c')
  3. Fill in the sign in form.
  4. Click log in.
  5. Shows generic error page and prints the above error on the server.

Expected behavior

Should be allowed to sign in without needing an access_token

KillianGDK-FDTI commented 1 year ago

Here is my working configuration :

        AzureADB2C({
            issuer: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT_ID}/v2.0/`,
            wellKnown: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/v2.0/.well-known/openid-configuration`,
            authorization: {
                url: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/oauth2/v2.0/authorize`,
                params: { scope: B2C_CLIENT_ID }
            },
            token: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/oauth2/v2.0/token`,
            clientId: B2C_CLIENT_ID,
            clientSecret: B2C_CLIENT_SECRET,
            allowDangerousEmailAccountLinking: true
        })

Hope it helps

Painwraith commented 6 months ago

Here is my working configuration :

      AzureADB2C({
          issuer: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT_ID}/v2.0/`,
          wellKnown: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/v2.0/.well-known/openid-configuration`,
          authorization: {
              url: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/oauth2/v2.0/authorize`,
              params: { scope: B2C_CLIENT_ID }
          },
          token: `https://${B2C_TENANT}.b2clogin.com/${B2C_TENANT}.onmicrosoft.com/${B2C_POLICY}/oauth2/v2.0/token`,
          clientId: B2C_CLIENT_ID,
          clientSecret: B2C_CLIENT_SECRET,
          allowDangerousEmailAccountLinking: true
      })

Hope it helps

Thank you so much.