itpropro / nuxt-oidc-auth

OIDC (OpenID connect) focused auth module for Nuxt
https://nuxtoidc.cloud
MIT License
83 stars 22 forks source link

/auth/.../callback does not work in Azure static web app | Custom prefix for callback handlers #56

Open ebuzyuma opened 1 month ago

ebuzyuma commented 1 month ago

Hi,

I'm building a nuxt app with Azure B2C as entra provider and deploying it to Azure Static Web Apps.

The nuxt app itself works fine. But I have an issue after successful sign-in and in the callback handler. Namely, POST /auth/entra/callback does not go through to the backend. There are several constraints when API backend is used in static apps and one of them:

  • The API route prefix must be /api.

Therefore 405 method not allowed is shown after redirect.

What I get working is a custom handler /api/auth/[...].ts:

import { callbackEventHandler } from "nuxt-oidc-auth/runtime/server/lib/oidc.js";
import { setUserSession } from "nuxt-oidc-auth/runtime/server/utils/session.js";
import type { UserSession } from "nuxt-oidc-auth/runtime/types/session.js";

export default defineEventHandler(async (event) => {
  const newEvent = {
    ...event,
    path: event.path.substring(4),
  };

  return callbackEventHandler({
    async onSuccess(event, { user, callbackRedirectUrl }) {
      await setUserSession(event, user as UserSession);
      return sendRedirect(event, callbackRedirectUrl || ("/" as string));
    },
  })(newEvent);
});

Having a custom handler is ok. But importing the functions from the library is not best. I also used proxyRequest in that handler but then it returns 502 Bad Gateway.

I have it working with the workaround above. But maybe you know other solutions here? Or the library can be extended to have a custom prefix for (callback) handler?

itpropro commented 1 month ago

Hey, I have several questions,

Also keep in mind, B2C is not formally OIDC compliant, only Entra External ID is (which is basically the successor of B2C, as B2C is not in active development anymore afaik).

I will try to reproduce as best as I can as soon as you shared your configs!

ebuzyuma commented 1 month ago

Hey, thanks for the quick reply!

Answers:

Setup to reproduce:

This is a part of nuxt config

{

  oidc: {
    providers: {
      entra: {
        redirectUri: "http://localhost:3000/auth/entra/callback",
        clientId: "<app client id>",
        clientSecret: "",
        audience: "<app client id>",
        authorizationUrl: "<Azure AD B2C OAuth 2.0 authorization endpoint (v2)>",
        tokenUrl: "<Azure AD B2C OAuth 2.0 token endpoint (v2)>",
        logoutUrl: "<Azure AD B2C OAuth 2.0 logout endpoint (v2)>",
        logoutRedirectUri: "http://localhost:3000",
        userNameClaim: "name",
        nonce: true,
        responseType: "code id_token",
        scope: [ "openid" ],
        validateIdToken: true,
        exposeIdToken: true,
        validateAccessToken: true,
        exposeAccessToken: true,
        responseMode: "form_post",
      },
    },
    middleware: {
      globalMiddlewareEnabled: false,
      customLoginPage: false,
    },
    devtools: true,
  },
  nitro: {
    preset: "azure",
    storage: {
      oidc: {
        driver: "fs",
        base: ".data/storage/oidc",
      },
    },
  },
}

You don't have to deploy it to azure. After setup, run build and preview it with: npx @azure/static-web-apps-cli start .output/public --api-location .output/server

itpropro commented 1 month ago

I don't have a B2C tenant available currently, I just know that B2C is officially not OIDC compliant. For SWA, I know that Entra External ID offers what you mentioned, meaning local accounts plus external social accounts login and would be the better choice as the default swa model with the proxy in the middle is not really made for ssr based auth. I would really recommend using the native integration of Static Web Apps, as that is one of the huge benefits of using that platform. That way you have auth completely handled for you and still have all the external id features. You would have everything available via the injected swa proxy auth route and you could even use that from an spa and don't worry about security.