Не удается получить доступ к авторам (NextAuth 5) на стороне сервера токенов доступа в Next.js 15 с серверной частью Django

Я пытаюсь настроить аутентификацию в моем Next.js приложении, используя NextAuth.js серверную часть Django. В качестве поставщика Oauth я использую django-oauth-toolkit.

Цель состоит в том, чтобы передавать токен доступа в заголовке авторизации при выполнении запросов к API Django.

Я успешно настроил провайдера OAuth2 в Auth.js и могу войти в систему через систему аутентификации Django.

Однако, когда я пытаюсь получить токен доступа на стороне сервера в моем Next.js приложении (в серверном компоненте), я не могу его найти.

Я стараюсь следовать официальному руководству по бэкендам третьих частей: https://github.com/nextauthjs/next-auth-example

Я использую Extjs 15.1.7 и Authjs (NextAuth.js версия 5)

Вот соответствующий код:

src\auth.ts

import NextAuth from "next-auth"
import "next-auth/jwt"

declare module "next-auth" {
  interface Session {
    accessToken?: string
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    accessToken?: string
  }
}

const DJANGO_URL = process.env.NEXT_PUBLIC_DJANGO_URL;
const NEXTJS_URL = process.env.NEXT_PUBLIC_NEXTJS_URL;

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [{
    id: "django", // signIn("my-provider") and will be part of the callback URL
    name: "Django", // optional, used on the default login page as the button text.
    type: "oauth", // or "oauth" for OAuth 2 providers
    userinfo: `${DJANGO_URL}/api/o/userinfo/`,
    token: `${DJANGO_URL}/api/o/token/`,
    wellKnown: `${DJANGO_URL}/api/o/.well-known/openid-configuration/`,
    authorization: {
      params: {
        prompt: "login",
        scope: "openid read write",
        redirect_uri: `${NEXTJS_URL}/api/auth/callback/django`,
      },
    },
    issuer: `${DJANGO_URL}/api/o`, // to infer the .well-known/openid-configuration URL
    clientId: process.env.DJANGO_ID,
    clientSecret: process.env.DJANGO_SECRET,
    async profile(profile) {
      return{
        id: profile.sub,
        email: profile.email,
      }
    },
  }],
  pages:{
    signIn: "/login",
  },
  session: { strategy: "jwt" },
  callbacks: {
    authorized: async ({ auth }) => {
      // Logged in users are authenticated, otherwise redirect to login page
      return !!auth
    },
    jwt({ token, trigger, session, account }) {
      if (trigger === "update") token.name = session.user.name
      if (account?.provider === "django") {
        return { ...token, 
                 accessToken: account.access_token 
               }
      }
      return token
    },
    async session({ session, token }) {
      if (token?.accessToken) session.accessToken = token.accessToken

      return session
    },
  },
})

и затем я настроил прокси-сервер в качестве руководства, чтобы каждый запрос, начинающийся с "/api/", перенаправлялся на серверную часть с токеном доступа в заголовках, таким образом:

src\app\api\ [...proxy]\route.ts

import { auth } from "@/auth"
import { NextRequest, NextResponse } from "next/server"

async function handler(request: NextRequest) {
  console.log("📢 Route Handler activated!")

  const session = await auth()
  console.log("🧐 Session:", session)

  if (!session?.accessToken) {
    console.log("⛔ No token in session.");
    return NextResponse.json("Error Unauthorized 401")
  }

  const headers = new Headers(request.headers)
  headers.set("Authorization", `Bearer ${session?.accessToken}`)
  headers.set("Accept", "application/json")

  let backendUrl = "https://localhost:8000/"

  let url = request.nextUrl.href.replace(request.nextUrl.origin, backendUrl)
  let result = await fetch(url, { 
    headers, body: 
    request.body,
    credentials: "include"
   })

  let data = await result.json();

  return NextResponse.json(data)
}

export const dynamic = "force-dynamic"

export { handler as GET, handler as POST }

а затем серверный компонент, максимально простой:

src\компоненты\usermenu.tsx

async function getUserData() {
  const res = await fetch("https://localhost:3000/api/users/customuser/me/"); //request handled by the [...proxy] 

  if (!res.ok) {
    throw new Error("Error retrieving user data");
  }

  return res.json();
}

export default async function UserProfilePage() {
  const userData = await getUserData();

  return (
    <div>
      {JSON.stringify(userData, null, 2)}
    </div>
  );
}

Однако, когда запрос обрабатывается на стороне сервера (в обработчике маршрута API или серверном компоненте), токен недоступен. Я пытался зарегистрировать токен и проверить файлы cookie, но, похоже, ничего не работает.

Я использую HTTPS локально как для своих приложений Next.js, так и для приложений Django, и я создал свои SSL-сертификаты вручную.

У меня есть следующие вопросы:

  • Как я могу корректно получить следующий токен аутентификационного доступа на стороне сервера в моем приложении Next.js?
  • Есть ли какой-то особый способ настроить мой сеанс или файлы cookie, чтобы убедиться, что токен доступен на стороне сервера?
  • Может ли проблема быть связана с SSL-сертификатами, которые я использую локально, и как я могу это решить, если да?
  • Что-то не так с тем, как я использую auth() или получаю доступ к сеансу в моем приложении Next.js?

Большое вам спасибо за уделенное время и помощь. Я искренне ценю ваш опыт и содействие в решении этой проблемы! Я не могу выразить словами, как я благодарен вам за вашу поддержку. Ваши идеи были бесценны, и я благодарен вам за то, что вы помогли мне пройти через это!

Вернуться на верх