Nuxt.js — SSR & Authentication

Nuxt.js is a server-side rendering framework build on top of Vue.js. It’s very easy to get started with and it allows to deploy your app in minutes.

SSR is a great solution to get rid of all the SEO problems that come with single page apps but unfortunately it brings another problem: authentication can be a real pain to manage.

Nuxt.js website provide an example called “Auth Routes” (https://nuxtjs.org/examples/auth-routes). It shows how to restrict the access of a page with a middleware but the checking is client-side and the server-side rendered content is the same whether you are authentified or not.

What if we want to SSR a specific content? There is a solution!

SSR usually works that way: the client make a request, for example let’s say it asks “/articles/page/1”, the SSR framework calls an API wich return JSON data then it generates the page and sends it to the client.

Well, what we miss here is to be able to specify a token or something that say we are authentified. Maybe a cookie contening the auth token? It can be read through the headers so our SSR framework can access it and pass it to the API.

First things first, we need to setup two plugins:

import axios from 'axios'
let options = {}
if (process.SERVER_BUILD) {
options.baseURL = `http://api:3030`
}
let ax = {
options,
create: (token) => {
options.headers = {
Authorization: token
}
return axios.create(ax.options)
}
}
export default ax

This one allows to pass to Axios (a promise based HTTP client for the browser and node.js) a token in his requests.

const getCookie = function(cname, req) {
let name = cname + "="
let decodedCookie
if (typeof window === 'undefined') decodedCookie = decodeURIComponent(req.headers.cookie)
else decodedCookie = decodeURIComponent(document.cookie)
var ca = decodedCookie.split(';')
for(let i = 0; i <ca.length; i++) {
let c = ca[i]
while (c.charAt(0) == ' ') {
c = c.substring(1)
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length)
}
}
return ""
}
export default getCookie

And this one to extract our token from the cookie.
Then you simply use them inside an “async fetch” method:

import axios from '~plugins/axios'
import getCookie from '~plugins/getCookie'
export default {
async fetch ({ store, isServer, req, redirect }) {
if(isServer) {
const ax = axios.create(getCookie('token', req))
try {
let { data } = await ax.get('/populate')
if(data.store && data.store.user) store.commit('user/setData', data.store.user)
else redirect('/login')
} catch(e) {}
}
}
}