To solve this problem, I relied on ADAL JS . I made a sample Vue + Vue-Router application available here - but I will include the important parts below.
In your package.json:
"dependencies": { "adal-angular": "^1.0.15", "vue": "^2.5.2", "vue-router": "^3.0.1" },
Basic wrapper module for 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(); } }
At the entry point to the application (main.js, if you used vue-cli):
import Vue from 'vue' import App from './App' import router from './router' import authentication from './authentication'
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
Below is an example of a vue-resource http interceptor, but any method would 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(); }); });
Hope this saves someone some time :)