Azure / static-web-apps

Azure Static Web Apps. For bugs and feature requests, please create an issue in this repo. For community discussions, latest updates, kindly refer to the Discussions Tab. To know what's new in Static Web Apps, visit https://aka.ms/swa/ThisMonth
https://aka.ms/swa
MIT License
318 stars 53 forks source link

Next.js with next auth middleware not working #1254

Open pauloreis7 opened 10 months ago

pauloreis7 commented 10 months ago

The Problem

I am using Next.js version 13.4.15 with next-auth version 4.23. I have created an authentication middleware to protect authenticated routes with Next-Auth locally, and it works perfectly. However, when deploying in the Azure Web Static Apps environment, the middleware does nothing, allowing unauthenticated users to access the protected routes.

To Reproduce Steps to reproduce the behavior:

  1. Create a Next.js app using create-next-app.
  2. Add next-auth with Azure AD as the provider.
  3. Create the default middleware for authenticating next-auth protected routes.
  4. Deploy the app to Azure Web Static Apps.
  5. Note that when navigating through authenticated routes, the middleware is not activated, allowing navigation through protected routes.

Expected behavior next-auth middleware redirects unauthenticated users trying to access a page that requires authentication.

Screenshots dependencies:

"dependencies": {
    "@hookform/resolvers": "^3.1.1",
    "@radix-ui/react-avatar": "^1.0.3",
    "@radix-ui/react-checkbox": "^1.0.4",
    "@radix-ui/react-dialog": "^1.0.4",
    "@radix-ui/react-dropdown-menu": "^2.0.5",
    "@radix-ui/react-scroll-area": "^1.0.4",
    "@radix-ui/react-select": "^1.2.2",
    "@radix-ui/react-slot": "^1.0.2",
    "@tanstack/react-query": "^4.32.1",
    "@types/node": "20.4.5",
    "@types/react": "18.2.18",
    "@types/react-dom": "18.2.7",
    "autoprefixer": "10.4.14",
    "axios": "^1.4.0",
    "clsx": "^2.0.0",
    "dotenv-expand": "^10.0.0",
    "next": "^13.4.15",
    "next-auth": "^4.23.0",
    "next-themes": "^0.2.1",
    "postcss": "8.4.27",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-hook-form": "^7.45.2",
    "react-icons": "^4.10.1",
    "react-toastify": "^9.1.3",
    "sharp": "^0.32.4",
    "tailwindcss": "3.3.3",
    "typescript": "5.1.6",
    "zod": "^3.21.4"
  },

middleware:

export { default } from "next-auth/middleware"

export const config = { matcher: ["/dashboard"] }

next auth config:

import type { AuthOptions } from 'next-auth'
import AzureADProvider from 'next-auth/providers/azure-ad'

import { getUserRolesByAdMemberOf } from '@/utils/roles'

import { microsoftAdApi } from '@/lib/axios'

export const authOptions: AuthOptions = {
  providers: [
    AzureADProvider({
      clientId: process.env.NEXT_PUBLIC_AZURE_AD_CLIENT_ID,
      tenantId: process.env.NEXT_PUBLIC_AZURE_AD_TENANT_ID,
      clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
      userinfo: {
        async request(context) {
          const { data } = await microsoftAdApi(
            '/me?$select=id,displayName,mail,accountEnabled,userType&$expand=memberOf($select=displayName)',
            {
              headers: {
                Authorization: `Bearer ${context.tokens.access_token}`,
              },
            },
          )

          return {
            id: data.id,
            email: data.mail,
            name: data.displayName,
            memberOf: getUserRolesByAdMemberOf(data.memberOf),
          }
        },
      },
      profile(userinfo) {
        return {
          id: userinfo.id,
          email: userinfo.mail,
          name: userinfo.name,
          memberOf: userinfo.memberOf,
        }
      },
      authorization: {
        params: {
          scope: 'openid email profile',
        },
      },
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  pages: {
    signIn: '/',
  },
  callbacks: {
    async redirect({ url, baseUrl }) {
      // These conditions redirect user after a successful login
      if (url.startsWith('/')) return `${baseUrl}${url}`
      else if (new URL(url).origin === baseUrl) return url

      return baseUrl
    },
    async jwt({ account, token, user, profile }) {
      if (profile) {
        user.email = profile.email
        token.name = profile.name
        token.email = profile.email
        token.memberOf = profile.memberOf
      }

      if (account?.access_token) {
        token.accessToken = account.access_token

        microsoftAdApi.defaults.headers.common.Authorization = `Bearer ${token.accessToken}`
      }

      return token
    },
    async session({ token, session }) {
      if (token) {
        session.accessToken = token.accessToken
        session.memberOf = token.memberOf
      }

      return session
    },
  },
}

Device info (if applicable):

Hmoulvad commented 5 months ago

We are experiencing the same thing, any news on this?

OsoThevenin commented 3 weeks ago

Just had the same issue as @pauloreis7 Fixed it by setting AUTH_TRUST_HOST to true

https://authjs.dev/getting-started/deployment#auth_trust_host