简体   繁体   中英

Auth0 route guard not working with Nuxt middleware

What is the correct pattern to implement Auth0 route guards in Nuxt?

I've adapted the Auth0 sample code to create the following middleware:

import {getInstance} from '~/plugins/auth';

export default function () {
  const authService = getInstance();

  const fn = () => {
    // If the user is authenticated, continue with the route
    if (!authService.isAuthenticated) {
      authService.loginWithRedirect({
        appState: {targetUrl: 'http://localhost:3000'},
      });
    }
  };

  // If loading has already finished, check our auth state using `fn()`
  if (!authService.loading) {
    return fn();
  }

  // Watch for the loading property to change before we check isAuthenticated
  authService.$watch('loading', loading => {
    if (loading === false) {
      return fn();
    }
  });
}

Notice that before the authentication status of Auth0 can be accessed, we must wait for the the instance to finish loading. The Auth0 sample code does this by using $watch .

My middleware code "works" but has the issue of briefly displaying the protected pages before the async $watch triggers. Is there any way to wait and block the route from continuing to render until Auth0 has finished loading and its auth status can be accessed?

I've also tried using almost the exact same code Auth0 provides without my own modifications within the beforeRouteEnter hook of the Nuxt pages. This has the same issue which begs the question as to why the Auth0 example presumably works in VueJS using beforeRouteEnter but not in Nuxt?

Solved it!

A middleware can be asynchronous. To do this return a Promise or use async/await.

https://nuxtjs.org/docs/2.x/directory-structure/middleware/

I simply wrapped my middleware script in a promise. I resolved it if the user is able to pass, otherwise I redirected them to the Auth0 login.

import {getInstance} from '~/plugins/auth';

export default function () {
  return new Promise(resolve => {
    const authService = getInstance();

    const fn = () => {
      // If the user is authenticated, continue with the route
      if (!authService.isAuthenticated) {
        return authService.loginWithRedirect({
          appState: {targetUrl: 'http://localhost:3000'},
        });
      }
      resolve();
    };

    // If loading has already finished, check our auth state using `fn()`
    if (!authService.loading) {
      return fn();
    }

    // Watch for the loading property to change before we check isAuthenticated
    authService.$watch('loading', loading => {
      if (loading === false) {
        return fn();
      }
    });
  });
}

It was also important to return the loginWithRedirect to make sure that it didn't go on to resolve the promise outside of the if block.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM