1

I created a Nuxt app that uses Django on the backend, i'm using the standard Django Session Authentication, so when i log in from Nuxt, a session cookie is set in my browser.

I've been trying for days to find a way to restrict some pages to authenticated users only, but i don't seem to find any working approach to do that. I need to check if the user is logged in before the page is loaded, so i tried to use a middleware but middleware won't work at all because the middleware is executed from server side (not client side) so there won't be any cookie in the request.

At this point, is there any other way to do this from SSR? Here is my request:

export default async function (context) {
  axios.defaults.withCredentials = true;
  return axios({
    method: 'get',
    url: 'http://127.0.0.1:8000/checkAuth',
    withCredentials: true,
  }).then(function (response) {
    //Check if user is authenticated - response is always False
  }).catch(function (error) {
    //Handle error
  });
}
JayK23
  • 287
  • 1
  • 15
  • 49

2 Answers2

2

If you are running Nuxt in SSR mode as server, you can access the cookie headers to find out if the user has a certain cookie. Packages like cookieparser (NPM) can easily do that for you.

But as you already found out, you can't do that in a middleware. What you could use instead is the nuxtServerInit action in your store (Docs). This action is run on the server and before any middleware gets executed. In there you can use cookieparser to get the user's cookies, authenticate them and save the any information you need in the store.

Later you can access the store in your middleware and for example redirect the user.

Florian Pallas
  • 584
  • 1
  • 5
  • 10
  • Thank you a lot! There is something i don't understand here: i tried a similar tool called cookie-universal and it allowed me to get the user's cookie from the middleware too, but then the problem was that there was no way to send the cookie in the request. How is nuxtServerInit different from the middleware? – JayK23 Apr 09 '21 at 08:14
2

actually you can get cookies in a middleware.... Ill put my example, but the answer above is more correct .

middleware/auth.js

import * as cookiesUtils from '~/utils/cookies'

export default function ({ route, req, redirect }) {
  const isClient = process.client
  const isServer = process.server

  const getItem = (item) => {
    // On server
    if (isServer) {
      const cookies = cookiesUtils.getcookiesInServer(req)
      return cookies[item] || false
    }

    // On client
    if (isClient) {
      return cookiesUtils.getcookiesInClient(item)
    }
  }

  const token = getItem('token')
  const { timeAuthorized } = cookiesUtils.authorizeProps(token)


  const setRedirect = (routeName, query) => {
    return redirect({
      name: routeName,
      query: query
        ? {
            redirect: route.fullPath
          }
        : null
    })
  }


  // strange bug.. nuxt cant redirect '/' to '/login'
  if (route.path === '/') {
    setRedirect('users')
  }

  if (!route.path.match(/\/login\/*/g) && !timeAuthorized) {
    setRedirect('login', true)
  }

  
}

utils/cookies.js

import Cookie from 'js-cookie'
import jwtDecoded from 'jwt-decode'

/*
  TOKEN
*/
// Get server cookie
export const getcookiesInServer = (req) => {
  const serviceCookie = {}
  if (req && req.headers.cookie) {
    req.headers.cookie.split(';').forEach((val) => {
      const parts = val.split('=')
      serviceCookie[parts[0].trim()] = (parts[1] || '').trim()
    })
  }

  return serviceCookie
}

// Get the client cookie
export const getcookiesInClient = (key) => {
  return Cookie.get(key) || false
}

export const setcookiesToken = (token) => {
  Cookie.set('token', token)
}
export const removecookiesToken = () => {
  Cookie.remove('token')
}

export const authorizeProps = (token) => {
  const decodeToken = token && jwtDecoded(token)

  const timeAuthorized = (decodeToken.exp > Date.now() / 1000) || false

  return {
    timeAuthorized
  }
}
  • Thank you a lot! Actually i managed to get the users cookie in the middleware using a tool called cookie-universal, the prbolem i'm having now is with sending that cookie in the request from Axios – JayK23 Apr 09 '21 at 08:15
  • Just pick it in axios interceptor like here https://stackoverflow.com/questions/52737078/how-can-you-use-axios-interceptors. And put it in your header - request.headers.common['Authorization'] = `Bearer ${token}` – Levy_from_Odessa Apr 09 '21 at 08:41
  • I tried that too, but it gave me a Cannot set property 'Authorization' of undefined when running it in the interceptor – JayK23 Apr 09 '21 at 08:53