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.
Enable Azure Active Directory in your App Service app. Sign in to the Azure portal and navigate to your app. Select Authentication in the menu on the left. Click Add identity provider.
Azure AD Benefit 1 Azure Active Directory is a secure online authentication store, which can contain users and groups. Users have a username and a password which are used when you sign into an application that uses Azure AD for authentication.
The user enters their password into the Azure AD sign in page, and then selects the Sign in button. Azure AD, on receiving the request to sign in, places the username and password (encrypted by using the public key of the Authentication Agents) in a queue.
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.
"dependencies": { "adal-angular": "^1.0.15", "vue": "^2.5.2", "vue-router": "^3.0.1" },
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(); } }
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 } }); });
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;
import authentication from './authentication' ... computed: { isAuthenticated() { return authentication.isAuthenticated(); } }, methods: { logOut() { authentication.signOut(); } }
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 :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With