Защищенные маршруты с использованием JWT-токенов в NextJS + Django

Я начинаю новое приложение NextJS, в котором я использую Django в качестве API.

Я использую JWT-токены для аутентификации/авторизации и хотел создать защищенные маршруты. После изучения кучи руководств, видео и других вещей в Интернете, вот что я придумал:

Я создал экземпляр axios (api.js) (где я пытался перехватить запросы для установки заголовка Authorization):

import axios from "axios";
import Cookies from "js-cookie";


const api = axios.create({
  baseURL: "http://127.0.0.1:8000/api/",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json",
  },
});

api.interceptors.request.use((request) => {
  const token = Cookies.get("accessToken");
  if (token) {
    api.defaults.headers.Authorization = `Bearer ${token.access}`;
  }
  return request;
});

export default api;

И AuthService.js (где я устанавливаю cookie при входе в систему):

    import Cookies from "js-cookie";
    import api from "./api";
    
    export const AuthService = {
      login: async (email, password) => {
        const { data: token } = await api.post("token/", { email, password });
        console.log(token);
        if (token) {
          console.log("Got token");
          Cookies.set("accessToken", token.access, { expires: 60 });
          api.defaults.headers.Authorization = `Bearer ${token.access}`;
          const { data: user } = await api.get("users/current/");
          console.log("Got user", user);
    
          return user;
        }
      },
    
      logout: async () => {
        Cookies.remove("accessToken");
        delete api.defaults.headers.Authorization;
      },
    
      getUser: async () => {
        try {
          const { data: user } = await api.get("users/current/");
          return user;
        } catch (error) {
          console.log("Error", error);
        }
      },
    };

Затем, в моем AuthContext у меня есть функция более высокого порядка (requireAuthentication), которая принимает другую функцию (в моем случае getServerSideProps) и перенаправляет на страницу входа, если токен доступа не установлен или является недействительным:

const AuthContext = createContext({});

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  const login = async (email, password) => {
    ...
  };

  const logout = () => {
    ...
  };

  const getUser = async () => {
    ...
  };

  const contextValues = {
    ...
  };

  return (
    <AuthContext.Provider value={contextValues}>
      {children}
    </AuthContext.Provider>
  );
}

export default AuthContext;

export function requireAuthentication(gssp) {
  return async (context) => {
    const { req } = context;

    if (req.cookies) {
      const accessToken = req.cookies["accessToken"];

      try {
        const user = await AuthService.getUser();
        console.log("user", user);

        if (!accessToken || !user || !user.email) {
          return {
            redirect: {
              permanent: false,
              destination: "/login",
            },
          };
        }
      } catch (error) {
        return {
          redirect: {
            permanent: false,
            destination: "/login",
          },
        }; 
      }
    }

    return gssp(context);
  };
}

Затем я могу использовать эту функцию высшего порядка для компонентов, которые мне нужно "защитить", следующим образом:

import { requireAuthentication } from "../../contexts/AuthContext";

export default function Dashboard({ props }) {
  return (
    <div>
      <h1>Dashboard</h1>
    </div>
  );
}

export const getServerSideProps = requireAuthentication((context) => {
  // normal `getServerSideProps` code here
  return {
    props: {}, // will be passed to the page component as props
  };
});

Кажется, я знаю, почему это не работает - когда я перехватываю запросы, куки не определяются, потому что я использую getServerSideProps, а куки находятся на стороне клиента.

Из того, что я прочитал, я могу использовать куки httponly, чтобы эта стратегия работала, но я не знаю как.

Является ли подход, который я использую, обычным/хорошим? Может ли кто-нибудь помочь мне с httponly cookie, если это решит мою проблему?

Пожалуйста, дайте мне знать, если у вас есть предложения и советы о том, как иметь "защищенные маршруты" с использованием JWT-токенов.

Спасибо.

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