'use strict'; angular.module('app').factory('authInterceptorService', ['$injector', '$q', '$window', '$location', 'config', 'userAuth', '$rootScope', 'fullScreenLoaderContext', authInterceptorService]); //interceptor that adds an auth header to the http request if required function authInterceptorService($injector, $q, $window, $location, configuration, userAuth, $rootScope, fsl) { var tokenRefreshing = false; var authInterceptorServiceFactory = { request: request, responseError: responseError }; initialize(); function initialize() { if (window && window.OData && window.OData.request) { var base = window.OData.request; window.OData.request = function (request, success, error, handler, httpClient, metadata) { request.headers = request.headers || {}; //get the token for the user var tokenData = userAuth.getAuthToken(); // Get the currently set role token var roleData = userAuth.getRoleToken(); if (tokenData) { request.headers.Authorization = 'Bearer ' + tokenData.access_token; configuration.authenticated = true; } if (roleData) request.headers["X-Current-Role-Token"] = roleData.token; return base(request, success, error, handler, httpClient, metadata); }; } } function request(config) { //do nowt for JSONP requests if (config.method === 'JSONP') return config; if (!config.url) return config; if (config.url.indexOf('.html') !== -1) return config; var requiresAuth = true; //check if this request URL doesn't require auth for (var i = 0; i < configuration.noAuthUrls.length; i++) { if (removeHttp(config.url).indexOf(configuration.noAuthUrls[i]) > -1) { requiresAuth = false; break; } } if (requiresAuth) { //the requested url does need to be authenticated config.headers = config.headers || {}; //get the token for the user var tokenData = userAuth.getAuthToken(); // Get the currently set role token var roleData = userAuth.getRoleToken(); //add a bearer token auth header with the stored access token if (tokenData) { config.headers.Authorization = 'Bearer ' + tokenData.access_token; configuration.authenticated = true; } //check if this request requires a role token //TODO: ensure all relevant apps have this config so we can remove the default list, //as at the moment it's impossible to specify no urls need role token var requiresRoleToken = false; if (!configuration.roleTokenUrls || configuration.roleTokenUrls.length == 0) { configuration.roleTokenUrls = ['mkmapps', 'openbadges.me', 'myshowcase.me', 'cuppacare.com', 'api', 'mkm-apigateway', 'localhost']; } for (var j = 0; j < configuration.roleTokenUrls.length; j++) { if (removeHttp(config.url).indexOf(configuration.roleTokenUrls[j]) > -1) { requiresRoleToken = true; break; } } //add a bearer token role header with the stored access token if (roleData && requiresRoleToken) { // If the role token has expired we need to generate a new one if (Date.now() > roleData.expires_on && $rootScope.currentRole && !tokenRefreshing) { // Make sure we only initiate this once tokenRefreshing = true; return userAuth.refreshRoleToken($rootScope.currentRole.roleId).then(function (token) { // Set the new role token userAuth.setRoleToken(token.token); config.headers["X-Current-Role-Token"] = token.token.token; tokenRefreshing = false; return config; }); } else { // Token is still valid so set the header of this request config.headers["X-Current-Role-Token"] = roleData.token; return config; } } else { return config; } } else { return config; } } function responseError(rejection) { // HTTP staus code of 498 means invalid token or expired token if (rejection.status === 498) { if (configuration.appCode == 'OB') { var auth = $injector.get('auth'); auth.logOut(); userAuth.setAuthToken(null); userAuth.setRoleToken(null); $location.path(configuration.loginRoute); window.location.reload(); return; } else { var reject = rejection; if ($rootScope.currentRole) { console.log(rejection); // Get a new role token userAuth.refreshRoleToken($rootScope.currentRole.roleId).then(function (token) { // Set the new role token userAuth.setRoleToken(token.token); }); } else { if (reject.config.url.indexOf('myusers') > -1) { var auth = $injector.get('auth'); auth.logOut(); userAuth.setAuthToken(null); userAuth.setRoleToken(null); $location.path(configuration.loginRoute); window.location.reload(); return; } } } } // TODO: We sign the user out if the badge report endpoints throw a 401. This usually occurs because the user has been given an admin role if (rejection.status === 401 && (rejection.config.url.indexOf(rolesUrl) > -1 || rejection.config.url.indexOf('api/mybadgereports') > -1)) { var requiresAuth = true; //check if this request URL doesn't require auth for (var i = 0; i < configuration.noAuthUrls.length; i++) { if ($location.$$path === configuration.noAuthUrls[i]) { requiresAuth = false; break; } } if (requiresAuth) { fsl.hide(); var auth = $injector.get('auth'); auth.logOut(); userAuth.setAuthToken(null); userAuth.setRoleToken(null); $location.path(configuration.loginRoute); return; } } //if (rejection.status == 500 && rejection.config.url.indexOf(rolesUrl) > -1) { // // User probably has no role // fsl.hide(); // var auth = $injector.get('auth'); // auth.logOut(); // userAuth.setAuthToken(null); // userAuth.setRoleToken(null); // $location.path(configuration.loginRoute); // window.location.reload(); // return; //} return $q.reject(rejection); } function removeHttp(url) { return url.replace(/^https?:\/\//, ''); } return authInterceptorServiceFactory; } angular.module('app').factory('noCacheInterceptorService', [noCacheInterceptorService]); //interceptor that adds a random query string param to the url for http requests - needed because IE caches data in some circumstances and this is a cache buster function noCacheInterceptorService() { var noCacheInterceptorServiceFactory = { request: request }; function request(config) { if (config.method === 'GET' && config.url.indexOf('api') > -1) { var separator = config.url.indexOf('?') === -1 ? '?' : '&'; config.url = config.url + separator + 'noCache=' + new Date().getTime(); } return config; } return noCacheInterceptorServiceFactory; }