How to create a middleware for check role in Nuxtjs

10,876

Solution 1

You can use this feature in Nuxt

export default function ({ $auth, redirect }) {
  if (!$auth.hasScope('admin')) {
    return redirect('/')
  }
}

The scope can be anything you want e.g Consultant, Editor etc.

Check the documentation

Updated

Since you are using Laravel You can have a role column in your user table e.g
$table->enum('role', ['subscriber', 'admin', 'editor', 'consultant', 'writer'])->default('subscriber');

Then create a API resource, check the documentation for more

To create a user resource, run this artisan

php artisan make:resource UserResource

Then in your resource, you can have something like this

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'phone' => $this->phone,
        'gender' => $this->gender,
        'country' => $this->country,
        'avatar' => $this->avatar,
        'role' => $this->role,
   ];    
}

Then you can import it to your controller like this

use App\Http\Resources\UserResource;

You can get the resource like this

            $userdata = new UserResource(User::find(auth()->user()->id));
            return response()->json(array(
                'user' => $userdata,
            ));

In Nuxt

To do authentication in Nuxt

Install nuxt auth and axios

Using YARN : yarn add @nuxtjs/auth @nuxtjs/axios
Or using NPM: npm install @nuxtjs/auth @nuxtjs/axios

Then register them in your nuxtconfig.js

modules: [
    '@nuxtjs/axios',
    '@nuxtjs/auth',
  ],

In your nuxtconfig.js, add this also

  axios: {
    baseURL: 'http://127.0.0.1:8000/api'
  },

auth: {
    strategies: {
      local: {
        endpoints: {
          login: { url: '/login', method: 'post', propertyName: 'access_token' },
          logout: { url: '/logout', method: 'post' },
          user: { url: '/user', method: 'get', propertyName: false }
        },
        tokenRequired: true,
        tokenType: 'Bearer',
        globalToken: true
        // autoFetchUser: true
      }
    }
  }

The URL been the endpoints

Check Documentation for more

To restrict certain pages in Nuxt to Specific User. > Create a middlweare e.g isadmin.js

Then add this

export default function ({ $auth, redirect }) {
  if (!$auth.hasScope('admin')) {
    return redirect('/')
  }
}

Then go to the Page, add the middleware

export default {
  middleware: 'isadmin'

Solution 2

The idea is that every page has its authority level. Then in middleware you can compare your current user authority level with the current page authority level, and if it's lower redirect the user. It's very elegant solution that was proposed by Nuxt.js creator. GitHub issue.

<template>
  <h1>Only an admin can see this page</h1>
</template>

<script>
export default {
  middleware: 'auth',
  meta: {
    auth: { authority: 2 }
  }
}
</script>

Then in your middleware/auth.js:

export default ({ store, route, redirect }) => {
  // Check if user is connected first
  if (!store.getters['user/user'].isAuthenticated) return redirect('/login')

  // Get authorizations for matched routes (with children routes too)
  const authorizationLevels = route.meta.map((meta) => {
    if (meta.auth && typeof meta.auth.authority !== 'undefined')
      return meta.auth.authority
    return 0
  })
  // Get highest authorization level
  const highestAuthority = Math.max.apply(null, authorizationLevels)

  if (store.getters['user/user'].details.general.authority < highestAuthority) {
    return error({
      statusCode: 401,
      message: 'Du måste vara admin för att besöka denna sidan.'
    })
  }
}
Share:
10,876
Jeremy
Author by

Jeremy

Updated on June 04, 2022

Comments

  • Jeremy
    Jeremy almost 2 years

    I'm trying to create a middleware for check role of my users.

    // middleware/is-admin.js
    export default function (context) {
      let user = context.store.getters['auth/user']
    
      if ( user.role !== 'admin' ) {
        return context.redirect('/errors/403')
      }
    }
    

    In my .vue file, I'm putting this on:

    middleware: [ 'is-admin' ]
    

    It works.

    Now, I'd like to check if the user also has another role. So, I create a new middleware:

    // middleware/is-consultant.js
    export default function (context) {
      let user = context.store.getters['auth/user']
    
      if ( user.role !== 'consultant' ) {
        return context.redirect('/errors/403')
      }
    }
    

    And in my .vue file:

    middleware: [ 'is-admin', 'is-consultant' ]
    

    Unfortunately, when I do that, if I visit the route with an administrator role, it does not work anymore.

    Can you tell me how I can create a middleware that checks multiple roles with Nuxt.js?

    Thank you!

  • xperator
    xperator over 3 years
    May I ask how can I feed nuxt the user roles? Do I need to have a role list in user object ( this.$auth.user ) ? I'm using Nuxt with Laravel (API server) btw.
  • xperator
    xperator over 3 years
    Thanks for the Laravel walkthrough. My issue is more on the Nuxt side though. I use Nuxt Auth module so it auto-fetches user data through /user endpoint. Right now I have added a role key added to user from laravel side, BUt I don't know how to check for that role in Nuxt
  • xtremeCODE
    xtremeCODE over 3 years
    Check my updated answer. Let me know if this solves the issue. Thanks.
  • xperator
    xperator over 3 years
    Thanks a lot for the detailed explanation. I looked into auth module source code and found that the hasScope method (by default) looks for a scope key in user object. So we have to change the role name to scope so Nuxt auth module can process it. Obviously we can also keep role name on laravel side and change scopeKey on the nuxt auth module options.
  • Muabazalm
    Muabazalm about 3 years
    Thank you, this is very helpful.