Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm setting up an app using the VueJS 2.x framework and it needs to authenticate users via the Azure Active Directory service. I already have "login info" (Auth and Token URLs) neccessary for the service.

So far, I've only encountered one article that shows the setup in VueJS, but it relies on a third party service (Auth0) - adding uneccessary convolution in the process.

How do you proceed when there aren't any VueJS npm modules that allow for doing authenticating easily? Or do you have to rely on a library outside of Vue like Adal JS?

Any suggestions would be helpful.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
604 views
Welcome To Ask or Share your Answers For Others

1 Answer

To solve this very problem, I leaned on ADAL JS. I've made a Vue + Vue-Router sample application available here - but I'll include the important pieces below.

In your package.json:

"dependencies": {
    "adal-angular": "^1.0.15",
    "vue": "^2.5.2",
    "vue-router": "^3.0.1"
},

A basic wrapper module for the ADAL JS library:

import AuthenticationContext from 'adal-angular/lib/adal.js'

const config = {
  tenant: 'your aad tenant',
  clientId: 'your aad application client id',
  redirectUri: 'base uri for this application',
  cacheLocation: 'localStorage'
};

export default {
  authenticationContext: null,
  /**
   * @return {Promise}
   */
  initialize() {
    this.authenticationContext = new AuthenticationContext(config);

    return new Promise((resolve, reject) => {
      if (this.authenticationContext.isCallback(window.location.hash) || window.self !== window.top) {
        // redirect to the location specified in the url params.
        this.authenticationContext.handleWindowCallback();
      }
      else {
        // try pull the user out of local storage
        let user = this.authenticationContext.getCachedUser();

        if (user) {
          resolve();
        }
        else {
          // no user at all - go sign in.
          this.signIn();
        }
      }
    });
  },
  /**
   * @return {Promise.<String>} A promise that resolves to an ADAL token for resource access
   */
  acquireToken() {
    return new Promise((resolve, reject) => {
      this.authenticationContext.acquireToken('<azure active directory resource id>', (error, token) => {
        if (error || !token) {
          return reject(error);
        } else {
          return resolve(token);
        }
      });
    });
  },
  /**
   * Issue an interactive authentication request for the current user and the api resource.
   */
  acquireTokenRedirect() {
    this.authenticationContext.acquireTokenRedirect('<azure active directory resource id>');
  },
  /**
   * @return {Boolean} Indicates if there is a valid, non-expired access token present in localStorage.
   */
  isAuthenticated() {
    // getCachedToken will only return a valid, non-expired token.
    if (this.authenticationContext.getCachedToken(config.clientId)) { return true; }
    return false;
  },
  /**
   * @return An ADAL user profile object.
   */
  getUserProfile() {
    return this.authenticationContext.getCachedUser().profile;
  },
  signIn() {
    this.authenticationContext.login();
  },
  signOut() {
    this.authenticationContext.logOut();
  }
}

In the app's entry point (main.js if you used vue-cli):

import Vue from 'vue'
import App from './App'
import router from './router'
import authentication from './authentication'

// Init adal authentication - then create Vue app.
authentication.initialize().then(_ => {
  /* eslint-disable no-new */
  new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App }
  });
});

For your Vue router configuration:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import authentication from '../authentication'

Vue.use(Router)

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      meta: {
        requiresAuthentication: true
      }
    }
  ]
})

// Global route guard
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuthentication)) {
    // this route requires auth, check if logged in
    if (authentication.isAuthenticated()) {
      // only proceed if authenticated.
      next();
    } else {
      authentication.signIn();
    }
  } else {
    next();
  }
});

export default router;

In your Vue components:

import authentication from './authentication'
...
computed: {
  isAuthenticated() {
    return authentication.isAuthenticated();
  }
},
methods: {
  logOut() {
    authentication.signOut();
  }
}

Add access token to request headers

The below is an example of a vue-resource http interceptor, but any method will do.

Vue.http.interceptors.push(function (request, next) {
  auth.acquireToken().then(token => {
    // Set default request headers for every request
    request.headers.set('Content-Type', 'application/json');
    request.headers.set('Ocp-Apim-Subscription-Key', 'api key');
    request.headers.set('Authorization', 'Bearer ' + token)
    // continue to next interceptor
    next();
  });
});

Hopefully this saves somebody a little time :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...