I'm able to make the authentication using JWT and angular-jwt, but now how can i redirect the user to the home page including the token in the header request? I'm using Spring Boot for the server side and i'd like to know how to serve this request.
this is the front-end's responsibility, you should redirect the user from angular, you can use the $location service.
as to the token you can store it in the $rootScope or in a client side cookie, here is an example of a jwt auth service i have wrote before it uses the $rootScope to store the client state.
note that this is not a production code.
app.service('AuthService', function ($rootScope, $http, $location) {
var service = this;
service.authenticate = function (credentials) {
$http({
'url': authUrl,
'method': 'POST',
'headers': {'Content-Type': 'application/json'},
'data': credentials
}).then(function (response) {
if (response.data.token && response.data.token.length > 0) {
$rootScope.authenticated = true;
$rootScope.jwtToken = response.data.token;
$location.path('/home');
} else {
$rootScope.logout();
}
}, function () {
$rootScope.logout();
});
$rootScope.logout = service.logout;
};
service.isAuthenticated = function () {
return $rootScope.authenticated;
};
service.logout = function () {
$rootScope.authenticated = false;
$rootScope.jwtToken = null;
};
});
Related
I'm facing issue on refreshing expired JWT token based on 401 (unauthorized) header response. What i want is when user get 401 (header) response, than a new (refresh) JWT should generated by calling specific service (api).
I'm sending XSRF-TOKEN & access_token (JWT) in header response and these are working fine. I even also can get refresh (expired) token by calling api manually. But can't get it worked with 401 (header) response.
I've a factory that take care of this promise and intercepts header requests. My (factory) code looks like this.
angular.module('myApp').factory('httpRequestInterceptor', httpRequestInterceptor);
function httpRequestInterceptor($cookies, $rootScope, $q, $location, $injector) {
var replays = [];
var refreshTokenPromise;
var factory = {
request: request,
responseError: responseError
};
return factory;
//////////
function requestTodoWhenDone() {
var token = store.get('token');
return $http({
method: 'POST',
url: ApiEndpoint.url,
params: {
grant_type: 'refresh',
id_token: $cookies.get('access_token')
}
})
.success(function(response) {
// Set the refreshed token.
$cookies.put('access_token', response.data.access_token);
})
.then(function(){
// Attempt to retry the request if request config is passed.
if( !angular.isUndefined(requestTodoWhenDone) && requestTodoWhenDone.length > 0 ) {
// Set the new token for the authorization header.
requestTodoWhenDone.headers = {
'Authorization': 'Bearer ' + $cookies.get('access_token')
};
// Run the request again.
return $http(requestTodoWhenDone);
}
});
}
//////////
// Add authorization token to headers
function request(config) {
config.headers = config.headers || {};
if ($cookies.get('access_token')) {
config.headers.Authorization = 'Bearer ' + $cookies.get('access_token');
}
return config;
}
// Intercept 401s and redirect you to login
function responseError(response, requestTodoWhenDone) {
if (response.status === 401 && $cookies.get('access_token')) {
return checkAuthorization(response);
}
return $q.reject(response);
/////////
function checkAuthorization(res) {
return $q(function(resolve, reject) {
var replay = {
success: function(){
$injector.get('$http')(res.config).then(resolve, reject);
},
cancel: function(){
reject(res);
}
};
replays.push(replay);
console.log(replays);
if (!refreshTokenPromise) {
refreshTokenPromise = $injector.get('requestTodoWhenDone') // REFRESH TOKEN HERE
.refreshToken()
.then(clearRefreshTokenPromise)
.then(replayRequests)
.catch(cancelRequestsAndRedirect);
}
});
////////////
function clearRefreshTokenPromise(auth) {
refreshTokenPromise = null;
return auth;
}
function replayRequests(auth) {
replays.forEach(function(replay) {
replay.success();
});
replays.length = 0;
return auth;
}
function cancelRequestsAndRedirect() {
refreshTokenPromise = null;
replays.forEach(function(replay) {
replay.cancel();
});
replays.length = 0;
$cookies.remove('token');
var $state = $injector.get('$state');
// SET YOUR LOGIN PAGE
$location.path('/login');
}
}
}
}
Based on above code I'm getting following error in console when token expires (401 response).
Console Error
Error: "[$injector:unpr] Unknown provider: requestTodoWhenDoneProvider <- requestTodoWhenDone
Any help on this would be highly appreciable.
Thanks.
Ok i ended up with different way that solves the issue. But i still can't be able to redirect user to login page when my token inactive time is also expires (this happens after jwt expires).
Here is the code.
authInterceptor.service.js
angular.module('someApp').factory('AuthorizationTokenService', AuthorizationTokenService);
AuthorizationTokenService.$inject = ['$q', '$injector', '$cookies'];
function AuthorizationTokenService($q, $injector, $cookies) {
// Local storage for token
var tokenVM = {
accessToken: null
};
// Subscribed listeners which will get notified when new Access Token is available
var subscribers = [];
// Promise for getting new Access Token from backend
var deferedRefreshAccessToken = null;
var service = {
getLocalAccessToken: getLocalAccessToken,
refreshAccessToken: refreshAccessToken,
isAccessTokenExpired: isAccessTokenExpired,
subscribe: subscribe
};
return service;
////////////////////////////////////
// Get the new Access Token from backend
function refreshAccessToken() {
// If already waiting for the Promise, return it.
if( deferedRefreshAccessToken ) {
return deferedRefreshAccessToken.promise
} else {
deferedRefreshAccessToken = $q.defer();
// Get $http service with $injector to avoid circular dependency
var http = $injector.get('$http');
http({
method: 'POST',
url: 'api_url',
params: {
grant_type: 'refresh',
id_token: $cookies.get('access_token')
}
})
.then(function mySucces(response) {
var data = response.data;
if( data ){
// Save new Access Token
$cookies.put('access_token', data.access_token);
if( $cookies.get('access_token') ) {
// Resolve Promise
deferedRefreshAccessToken.resolve(data.access_token);
// Notify all subscribers
notifySubscribersNewAccessToken(data.access_token);
deferedRefreshAccessToken = null;
}
}
}, function myError(error) {
deferedRefreshAccessToken.reject(error);
deferedRefreshAccessToken = null;
});
return deferedRefreshAccessToken.promise;
}
}
function getLocalAccessToken() {
// get accesstoken from storage - $cookies
if ( $cookies.get('access_token') ) {
var access_token = $cookies.get('access_token')
return access_token;
}
}
function isAccessTokenExpired() {
// Check if expiresAt is older then current Date
}
function saveToken(accessToken) {
// get accesstoken from storage - $cookies
var access_token = $cookies.put('access_token');
console.log('access_token ' + access_token);
return access_token;
}
// This function will call all listeners (callbacks) and notify them that new access token is available
// This is used to notify the web socket that new access token is available
function notifySubscribersNewAccessToken(accessToken) {
angular.forEach(subscribers, function(subscriber) {
subscriber(accessToken);
});
}
// Subscribe to this service. Be notifyed when access token is renewed
function subscribe(callback) {
subscribers.push(callback);
}
}
Than in config (app.js) I've following code which intercepts appropriate header(s) and refresh (request) api on 401 response.
Here is the config code
config.$inject = ['$stateProvider', '$urlRouterProvider', '$httpProvider'];
function config($stateProvider, $urlRouterProvider, $httpProvider) {
// Push httpRequestInterceptor
// $httpProvider.interceptors.push('httpRequestInterceptor');
//Intercept all http requests
$httpProvider.interceptors.push(['$injector', '$q', "AuthorizationTokenService", "$cookies", function ($injector, $q, AuthorizationTokenService, $cookies) {
var cachedRequest = null;
return {
request: function (config) {
//If request if for API attach Authorization header with Access Token
if (config.url.indexOf("api") != -1) {
// var accessToken = AuthorizationTokenService.getLocalAccessToken();
console.log('cookie ' + $cookies.get('access_token'));
config.headers.Authorization = 'Bearer ' + $cookies.get('access_token');
}
return config;
},
responseError: function (response) {
switch (response.status) {
// Detect if reponse error is 401 (Unauthorized)
case 401:
// Cache this request
var deferred = $q.defer();
if(!cachedRequest) {
// Cache request for renewing Access Token and wait for Promise
cachedRequest = AuthorizationTokenService.refreshAccessToken();
}
// When Promise is resolved, new Access Token is returend
cachedRequest.then(function(accessToken) {
cachedRequest = null;
if (accessToken) {
// Resend this request when Access Token is renewed
$injector.get("$http")(response.config).then(function(resp) {
// Resolve this request (successfully this time)
deferred.resolve(resp);
},function(resp) {
deferred.reject();
console.log('success: refresh token has expired');
});
} else {
// If any error occurs reject the Promise
console.log('error: refresh token has expired');
deferred.reject();
}
}, function(response) {
// If any error occurs reject the Promise
cachedRequest = null;
deferred.reject();
return;
});
return deferred.promise;
}
// If any error occurs reject the Promise
return $q.reject(response);
}
};
}]);
}
The code is working fine on 401 (response) case which happens when JWT expires. But its not redirecting me to login page (In this case I've added console in promise request in config instead of redirection code)
Please help on this, thanks...
Hi I followed a tutorial on the web. Everything work but I would encode bas64 with a secret or jwt but I don't know how. Can you help me please ?
(function () {
'use strict';
angular
.module('app')
.factory('AuthenticationService', Service);
function Service($http, $localStorage) {
var service = {};
service.Login = Login;
service.Logout = Logout;
return service;
function Login(username, password, callback) {
$http.post('/api/authenticate', { username: username, password: password })
.success(function (response) {
// login successful if there's a token in the response
if (response.token) {
// store username and token in local storage to keep user logged in between page refreshes
$localStorage.currentUser = { username: username, token: response.token };
// add jwt token to auth header for all requests made by the $http service
$http.defaults.headers.common.Authorization = 'Bearer ' + response.token;
// execute callback with true to indicate successful login
callback(true);
} else {
// execute callback with false to indicate failed login
callback(false);
}
});
}
function Logout() {
// remove user from local storage and clear http auth header
delete $localStorage.currentUser;
$http.defaults.headers.common.Authorization = '';
}
}
})();
and my service :
function run($rootScope, $http, $location, $localStorage) {
// keep user logged in after page refresh
if ($localStorage.currentUser) {
$http.defaults.headers.common.Authorization = 'Bearer ' + $localStorage.currentUser.token;
}
// redirect to login page if not logged in and trying to access a restricted page
$rootScope.$on('$locationChangeStart', function (event, next, current) {
var publicPages = ['/login'];
var restrictedPage = publicPages.indexOf($location.path()) === -1;
if (restrictedPage && !$localStorage.currentUser) {
$location.path('/login');
}
});
}
and the nodeJs :
function setupFakeBackend($httpBackend) {
var testUser = { username: 'test', password: 'test', firstName: 'Test', lastName: 'User' };
// fake authenticate api end point
$httpBackend.whenPOST('/api/authenticate').respond(function (method, url, data) {
// get parameters from post request
var params = angular.fromJson(data);
// check user credentials and return fake jwt token if valid
if (params.username === testUser.username && params.password === testUser.password) {
return [200, { token: 'fake-jwt-token' }, {}];
} else {
return [200, {}, {}];
}
});
$httpBackend.whenGET(/^\w+.*/).passThrough();
}
Thank you for your answer :)
JSON Web Tokens are composed of three JSON objects encoded to base 64 seperated by a . character.
header.payload.signiture
The example found at jwt.io eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ decodes to three JSON strings separated by .
If you wish to pull out the seperate componets you must first split the String
// es6
let myJwt = getToken();
let jwtParts = myJwt.split('.').map(part => btoa(part));
console.log(`header: ${jwtParts[0]}, payload: ${jwtParts[1]}, sig: ${jwtParts[2]}`)
On the server side you should be using the signing (for login) and verifying functions (for subsequent authentication) found in your JWT library i.e https://github.com/auth0/node-jsonwebtoken
Let me know if that was not quite what you are looking for
The following approach does not work:
angular.module('myApp.myModule').factory('MyResource', function($resource, $cookies) {
var token = $cookies.get('token');
var user = $cookies.get('username');
console.log ("Token: "+token+" User: "+user);
return $resource(
'http://my-rest-api/whatever/:id',
{
headers: {
'token': token,
'user': user
}
}
)});
Console shows the correct data, but they were not sent..
That's the part somewhere in the related Controller (excerpt):
var getEntryOne = MyResource.get({ id: 1 }, function() {
console.log("Result: "+getEntryOne);
});
I get the "Message: Token invalid", I see the request-http-headers in firebug, they were not setted.
You are setting headers for get request then it should be there in get option of $resource
$resource('http://my-rest-api/whatever/:id',{},{
get:{
method:"GET",
headers:{
'token': token,
'user': user
}
},
});
If you wanted to add this header information to each request, then you could have http inteceptor which will be add header information on each request.
app.service('MyResourceInterceptor', ['$cookies', function($cookies) {
var token = $cookies.get('token'),
user = $cookies.get('username'),
service = this;
service.request = function(config) {
config.headers['token'] = token;
config.headers['user'] = user;
return config;
};
}]);
app.config([ '$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('MyResourceInterceptor');
}]);
I'm writing an angularjs client for a token based restful API. The tokens in the API expire every hour so every time the token is expired in my client there should be a refresh token action.
The controller which handles the API call results looks like this:
angular.module('apitestApp')
.controller('MainCtrl', ['$rootScope', '$scope', 'httpService', function ($rootScope, $scope, httpService) {
$scope.messages = [];
var url = $rootScope.domainPath + $rootScope.apiPath + 'messages.json';
httpService.getRequest(url, {}).then(
function (data){
$scope.messages = data;
}
);
}]);
I have a service that makes the API calls using angularjs $resource
angular.module('apitestApp')
.service('httpService', ['$rootScope', '$resource', '$localStorage', function ($rootScope, $resource, $localStorage) {
this.getRequest = function (url, params){
var res = $resource(url, params, {
query: {
method: 'GET',
isArray: true,
headers: { 'Authorization': 'Bearer ' + $localStorage.token.access_token }
}
});
return res.query().$promise;
};
this.refreshToken = function (){
var url = $rootScope.domainPath + this.authPath;
var request = $resource(url);
return request.get({
client_id: this.clientId,
client_secret: this.secret,
grant_type: 'refresh_token',
refresh_token: $localStorage.token.refresh_token
},
function (data){
$localStorage.token = data;
}
).$promise;
};
}]);
And finally an interceptor that handles all unauthorized requests (401), refresh the access token and retries the failed request.
angular.module('apitestApp')
.factory('apiInterceptor', ['$q', '$injector', function ($q, $injector){
//Handling error codes
return {
response : function (response){
return response || $q.when(response);
},
responseError: function (rejection){
switch(rejection.status){
case 400:
console.log("Bad request");
break;
case 401:
var config = rejection.config;
var deferred = $q.defer();
var httpService = $injector.get('httpService');
httpService.refreshToken().then(deferred.resolve, deferred.reject);
return deferred.promise.then(function (){
return httpService.getRequest(config.url, config.params);
});
//break;
case 500:
console.log("Internal server error");
break;
default:
console.log("Another error");
break;
}
return $q.reject(rejection);
}
};
}]);
When the access token is valid, getRequest() method in my service successfully returns a promise, this is the same I want the interceptor to return but is not. In case the access token has expired the interceptor catches a 401 error, then updates the access token and finally makes the same request, the problem is that my controller doesn't get any response of it.
How can I perform a refresh token action and return the expected data on the behalf of the user? What am I doing wrong in the interceptor?
You're going to want to remove the $rootScope provider from the controller, that is not best practices for Angular as the controller has it's own scope inside of $rootScope. Services and Factories are okay to put on the $rootScope as it does not create it's own scope and that is where they will listen for their own events.
Also, it's best practice to put any asynchronous activity/HTTP calls into the services/factories. Just remember "skinny controllers, fat services".
Maybe try using an async handler that uses a sort of publish/subscribe design. Now, if it fails, it will call to update the stored value of messages once the getRequest function has completed async, triggering an update to the scope digest for any controller subscribed to the method:
Controller
angular.module('apitestApp')
.controller('MainCtrl', ['$scope', 'httpService', function ($scope, httpService) {
$scope.messages = [];
httpService.setPath();
httpService.onMessageReady($scope, function (messagesData) {
$scope.messages = messagesData;
});
}]);
Service
angular.module('apitestApp')
.service('httpService', ['$rootScope', '$resource', '$localStorage', function ($rootScope, $resource, $localStorage) {
var self = this;
this.messages = undefined;
this.setPath = function () {
self.getRequest($rootScope.domainPath + $rootScope.apiPath + 'messages.json', {});
};
this.getRequest = function (url, params) {
var res = $resource(url, params, {
query: {
method: 'GET',
isArray: true,
headers: { 'Authorization': 'Bearer ' + $localStorage.token.access_token }
}
});
return res.query().$promise.then(function (data) {
if (data) {
self.messages = data;
$rootScope.$broadcast('messagesReady');
}
});
};
this.refreshToken = function (){
var url = $rootScope.domainPath + this.authPath;
var request = $resource(url);
return request.get({
client_id: this.clientId,
client_secret: this.secret,
grant_type: 'refresh_token',
refresh_token: $localStorage.token.refresh_token
},
function (data){
$localStorage.token = data;
}
).$promise;
};
this.onMessageReady = function (scope, callback) {
callback(this.messages);
scope.$on('messagesReady', function () {
callback(this.messages);
});
};
}]);
I have a SPA app that uses Angular and Breeze, I need to implement the login functionality and I am new to Angular/Breeze. My architecture/code structure is as mentioned below:
login.html --> login.js -->datacontext/Service.js--->entityManagerFactory-->breezecontroller.cs -->repository->dbcontext-->database.
I am facing following challenges:
I am unable to show the login page as default, I am always getting Dashboard as a default page. I am looking for where I can route to login page.
2.breezecontroller -- This is inside controller, do I need to write my login method here?
All in all, I am looking for a complete login functionality implementation which following my architecture/code structure.
Here is a description of an approach that can be used in an Angular-based SPA. This particular example uses token-based OAuth authentication, but could be adapted to other authentication schemes. It is loosely based on the approach described at Authentication in AngularJS (or similar) based application
Some highlights are:
Authentication is managed through an auth service.
HTTP requests are intercepted, and:
When a 401 (access denied) error is detected and no user is logged in, an auth:login event is emitted (note - not broadcasted) on $rootScope
If a 401 error is detected while a user is logged in and an OAuth refresh token is available, an attempt is made to get a new access token based on the refresh token. An auth:login event is only emitted if the token cannot be refreshed.
Once a user has logged in, an Authorization header containing the user's access token is inserted onto each HTTP request so that the server can authenticate the user.
The application should watch for auth:login events and prompt the user for credentials. (I use an Angular-UI Bootstrap modal dialog for doing this.) Once credentials have been provided, the auth service's login function must be called to complete the login. After login is called, all pending HTTP requests that initially failed with a 401 error are retried. Alternatively, the auth service's loginCancelled function can be called to cancel the login, which will reject all pending HTTP requests.
For example:
angular.module('app', ['auth'])
.run(['$rootScope', 'auth', function ($rootScope, auth) {
$rootScope.$on(auth.options.loginRequiredEvent, function (event, details) {
// Display login dialog here, which will ultimately
// call `auth.login` or `auth.loginCancelled`
});
auth.restoreAuthDataFromStorage();
}]);
Here is an example of calling auth.login once the user has provided credentials:
auth.login(userName, password, isPersistent)
.success(function () {
// Dismiss login dialog here
})
.error(function (data, status) {
if (status === 401 || (data && data.error === 'invalid_grant')) {
failureMessage = 'Log in failed: Bad username or password';
} else {
failureMessage = 'Log in failed: Unexpected error';
}
});
Details of the logged in user are stored in window.sessionStorage or window.localStorage (based on whether a persistent login has been requested) to be able to be accessed across page loads.
Finally, here is the auth service itself.
var module = angular.module('auth');
module.provider('auth', function () {
var authOptions = {
tokenUrl: '/OAuthToken',
loginRequiredEvent: 'auth:loginRequired',
logoffEvent: 'auth:logoff',
loginEvent: 'auth:login',
authTokenKey: 'auth:accessToken'
};
this.config = function (options) {
angular.extend(authOptions, options);
};
// Get the auth service
this.$get = ['$rootScope', '$http', '$q', function ($rootScope, $http, $q) {
var authData = {
// Filled as follows when authenticated:
// currentUserName: '...',
// accessToken: '...',
// refreshToken: '...',
};
var httpRequestsPendingAuth = new HttpRequestsPendingAuthQueue();
// Public service API
return {
login: login,
refreshAccessToken: refreshAccessToken,
loginCancelled: loginCancelled,
logoff: logoff,
currentUserName: function () { return authData.currentUserName; },
isAuthenticated: function () { return !!authData.accessToken; },
getAccessToken: function () { return authData.accessToken; },
restoreAuthDataFromStorage: restoreAuthDataFromStorage,
_httpRequestsPendingAuth: httpRequestsPendingAuth,
options: authOptions,
};
function isAuthenticated() {
return !!authData.accessToken;
};
function restoreAuthDataFromStorage() {
// Would be better to use an Angular service to access local storage
var dataJson = window.sessionStorage.getItem(authOptions.authTokenKey) || window.localStorage.getItem(authOptions.authTokenKey);
authData = (dataJson ? JSON.parse(dataJson) : {});
}
function accessTokenObtained(data) {
if (!data || !data.access_token) {
throw new Error('No token data returned');
}
angular.extend(authData, {
accessToken: data.access_token,
refreshToken: data.refresh_token
});
// Would be better to use an Angular service to access local storage
var storage = (authData.isPersistent ? window.localStorage : window.sessionStorage);
storage.setItem(authOptions.authTokenKey, JSON.stringify(authData));
httpRequestsPendingAuth.retryAll($http);
}
function login(userName, password, isPersistent) {
// Data for obtaining token must be provided in a content type of application/x-www-form-urlencoded
var data = 'grant_type=password&username=' + encodeURIComponent(userName) + '&password=' + encodeURIComponent(password);
return $http
.post(authOptions.tokenUrl, data, { ignoreAuthFailure: true })
.success(function (data) {
authData = {
currentUserName: userName,
isPersistent: isPersistent
};
accessTokenObtained(data);
$rootScope.$emit(authOptions.loginEvent);
})
.error(function () {
logoff();
});
}
function refreshAccessToken() {
if (!authData.refreshToken) {
logoff();
return $q.reject('No refresh token available');
}
// Data for obtaining token must be provided in a content type of application/x-www-form-urlencoded
var data = 'grant_type=refresh_token&refresh_token=' + encodeURIComponent(authData.refreshToken);
return $http
.post(authOptions.tokenUrl, data, { ignoreAuthFailure: true })
.success(function (data) { accessTokenObtained(data); })
.error(function () { logoff(); });
}
function loginCancelled() {
httpRequestsPendingAuth.rejectAll();
}
function logoff() {
// Would be better to use an Angular service to access local storage
window.sessionStorage.removeItem(authOptions.authTokenKey);
window.localStorage.removeItem(authOptions.authTokenKey);
if (isAuthenticated()) {
authData = {};
$rootScope.$emit(authOptions.logoffEvent);
}
}
// Class implementing a queue of HTTP requests pending authorization
function HttpRequestsPendingAuthQueue() {
var q = [];
this.append = function (rejection, deferred) {
q.push({ rejection: rejection, deferred: deferred });
};
this.rejectAll = function () {
while (q.length > 0) {
var r = q.shift();
r.deferred.reject(r.rejection);
}
};
this.retryAll = function ($http) {
while (q.length > 0) {
var r = q.shift();
retryRequest($http, r.rejection.config, r.deferred);
}
};
function retryRequest($http, config, deferred) {
var configToUse = angular.extend(config, { ignoreAuthFailure: true });
$http(configToUse)
.then(function (response) {
deferred.resolve(response);
}, function (response) {
deferred.reject(response);
});
}
}
}];
});
module.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(['$injector', '$rootScope', '$q', function ($injector, $rootScope, $q) {
var auth;
return {
// Insert an "Authorization: Bearer <token>" header on each HTTP request
request: function (config) {
auth = auth || $injector.get('auth');
var token = auth.getAccessToken();
if (token) {
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + token;
}
return config;
},
// Raise a "login required" event upon "401 access denied" responses on HTTP requests
responseError: function(rejection) {
if (rejection.status === 401 && !rejection.config.ignoreAuthFailure) {
var deferred = $q.defer();
auth = auth || $injector.get('auth');
auth._httpRequestsPendingAuth.append(rejection, deferred);
if (auth.isAuthenticated()) {
auth.refreshAccessToken().then(null, function () {
$rootScope.$emit(auth.options.loginRequiredEvent, { message: 'Login session has timed out. Please log in again.' });
});
} else {
// Not currently logged in and a request for a protected resource has been made: ask for a login
$rootScope.$emit(auth.options.loginRequiredEvent, { rejection: rejection });
}
return deferred.promise;
}
// otherwise, default behaviour
return $q.reject(rejection);
}
};
}]);
}]);