/
http-auth-interceptor.js
122 lines (109 loc) · 3.86 KB
/
http-auth-interceptor.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*global angular:true, browser:true */
/**
* @license HTTP Auth Interceptor Module for AngularJS
* (c) 2012 Witold Szczerba
* License: MIT
*/
(function () {
'use strict';
angular.module('http-auth-interceptor', ['http-auth-interceptor-buffer'])
.factory('authService', ['$rootScope','httpBuffer', function($rootScope, httpBuffer) {
return {
/**
* Call this function to indicate that authentication was successfull and trigger a
* retry of all deferred requests.
* @param data an optional argument to pass on to $broadcast which may be useful for
* example if you need to pass through details of the user that was logged in
*/
loginConfirmed: function(data, configUpdater) {
var updater = configUpdater || function(config) {return config;};
$rootScope.$broadcast('event:auth-loginConfirmed', data);
httpBuffer.retryAll(updater);
},
/**
* Call this function to indicate that authentication should not proceed.
* All deferred requests will be abandoned or rejected (if reason is provided).
* @param data an optional argument to pass on to $broadcast.
* @param reason if provided, the requests are rejected; abandoned otherwise.
*/
loginCancelled: function(data, reason) {
httpBuffer.rejectAll(reason);
$rootScope.$broadcast('event:auth-loginCancelled', data);
}
};
}])
/**
* $http interceptor.
* On 401 response (without 'ignoreAuthModule' option) stores the request
* and broadcasts 'event:angular-auth-loginRequired'.
*/
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(['$rootScope', '$q', 'httpBuffer', function($rootScope, $q, httpBuffer) {
return {
responseError: function(rejection) {
if (rejection.status === 401 && !rejection.config.ignoreAuthModule) {
var deferred = $q.defer();
httpBuffer.append(rejection.config, deferred);
$rootScope.$broadcast('event:auth-loginRequired', rejection);
return deferred.promise;
}
// otherwise, default behaviour
return $q.reject(rejection);
}
};
}]);
}]);
/**
* Private module, a utility, required internally by 'http-auth-interceptor'.
*/
angular.module('http-auth-interceptor-buffer', [])
.factory('httpBuffer', ['$injector', function($injector) {
/** Holds all the requests, so they can be re-requested in future. */
var buffer = [];
/** Service initialized later because of circular dependency problem. */
var $http;
function retryHttpRequest(config, deferred) {
// Make room for new 'Authenticate' header value
delete config.headers['Authorization'];
function successCallback(response) {
deferred.resolve(response);
}
function errorCallback(response) {
deferred.reject(response);
}
$http = $http || $injector.get('$http');
$http(config).then(successCallback, errorCallback);
}
return {
/**
* Appends HTTP request configuration object with deferred response attached to buffer.
*/
append: function(config, deferred) {
buffer.push({
config: config,
deferred: deferred
});
},
/**
* Abandon or reject (if reason provided) all the buffered requests.
*/
rejectAll: function(reason) {
if (reason) {
for (var i = 0; i < buffer.length; ++i) {
buffer[i].deferred.reject(reason);
}
}
buffer = [];
},
/**
* Retries all the buffered requests clears the buffer.
*/
retryAll: function(updater) {
for (var i = 0; i < buffer.length; ++i) {
retryHttpRequest(updater(buffer[i].config), buffer[i].deferred);
}
buffer = [];
}
};
}]);
})();