Edward Hibbert
Edward Hibbert

Reputation: 137

API Platform + Nuxt - session management

I'm new to Nuxt and API Platform. I have created a basic server and client, and I'm trying to work out how to do session management.

I can log in purely on the client side, e.g. using the Nuxt Auth0 support. Or I can roll my own login. But that's just client side. Or I can use a form login on the Symfony server and post to it from the client, but that's just server side.

What I want is Nuxt to be able to tell whether or not I'm logged in to Symfony. What's the correct way to do this for a universal Nuxt app using API platform? Middleware? Server middleware? nuxtServerInit?

Upvotes: 1

Views: 5468

Answers (1)

Edward Hibbert
Edward Hibbert

Reputation: 137

I've got something that works, so I thought I'd post back here in case it's useful to other people to have some pointers.

The basic idea is:

  • On the Nuxt side use middleware to check whether or not we are logged in to the server before the rest of the page render happens.
  • On the API Platform side, set up JWT authentication as per here. This gives us a token which we will send on API requests to validate them.

In the Nuxt client, you need a store which handles the log in state. Here's my current WIP version (so I'm not claiming it's great code):

import axios from 'axios'

export default function({ store, redirect }) {
  store.commit('security/AUTHENTICATING')

  // Add token header if we have it.
  const token = store.state.security.token

  if (token) {
    axios.defaults.headers.common.Authorization = 'Bearer ' + token.toString()
  } else {
    axios.defaults.headers.common.Authorization = null
  }

  // Now make an API call to see if we're logged in.
  return axios
    .get(process.env.API + '/locations')
    .then(response => {
      // We're logged in.  No need to save the token - it's already in the store.
      store.commit('security/AUTHENTICATING_SUCCESS', null)
    })
    .catch(() => {
      // We're not logged in.
      if (store.state.security.isAuthenticated) {
        // ...but we thought we were. Correct our misapprehension.
        store.commit('security/LOGOUT')
      }

      // Ask them to log in.
      return redirect('/login')
    })
}

Then set up some middleware:

    import axios from 'axios'
    
    export default function({ store, redirect }) {
      store.commit('security/AUTHENTICATING')
    
      // Add token header if we have it.
      const token = store.state.security.token
    
      if (token) {
        axios.defaults.headers.common.Authorization = 'Bearer ' + token.toString()
      } else {
        axios.defaults.headers.common.Authorization = null
      }
    
      // Now make an API call to see if we're logged in.
      return axios
        .get(process.env.API + '/locations')
        .then(response => {
          // We're logged in.  No need to save the token - it's already in the store.
          store.commit('security/AUTHENTICATING_SUCCESS', null)
        })
        .catch(() => {
          // We're not logged in.
          if (store.state.security.isAuthenticated) {
            // ...but we thought we were. Correct our misapprehension.
            store.commit('security/LOGOUT')
          }
    
          // Ask them to log in.
          return redirect('/login')
        })
    }

I'm not completely happy with this yet, and I'm sure it could be better. But something along these lines is looking like it will do the job.

Upvotes: 1

Related Questions