SHOW:
|
|
- or go back to the newest paste.
1 | /* interceptor.js (angularjs 1.2.x version) */ | |
2 | angular.module('security.interceptor', ['security.retryQueue']) | |
3 | .factory('securityInterceptor', ['$injector', 'securityRetryQueue', '$cookieStore', function ($injector, queue, $cookieStore) { | |
4 | return { | |
5 | response: function(originalResponse) | |
6 | { | |
7 | return originalResponse; | |
8 | }, | |
9 | responseError: function (originalResponse) { | |
10 | var exception; | |
11 | if (originalResponse.headers){ | |
12 | exception = originalResponse.headers('x-eva-api-exception'); | |
13 | } | |
14 | if (originalResponse.status === 401 && (exception === 'token_not_found' || exception === 'token_expired')){ | |
15 | queue.pushRetryFn(exception, function retryRequest() { | |
16 | return $injector.get('$http')(originalResponse.config); | |
17 | }); | |
18 | } | |
19 | return originalResponse; | |
20 | } | |
21 | }; | |
22 | }]) | |
23 | .config(['$httpProvider', function($httpProvider) { | |
24 | $httpProvider.interceptors.push('securityInterceptor'); | |
25 | }]); | |
26 | ||
27 | ||
28 | /* interceptor.js (angularjs 1.0.8 version) */ | |
29 | ||
30 | angular.module('security.interceptor', ['security.retryQueue']) | |
31 | .factory('securityInterceptor', ['$injector', 'securityRetryQueue', function($injector, queue) { | |
32 | return function(promise) { | |
33 | return promise.then(null, function(originalResponse) { | |
34 | var exception; | |
35 | if(originalResponse.headers) { | |
36 | exception = originalResponse.headers('x-eva-api-exception'); | |
37 | } | |
38 | if(originalResponse.status === 401 && (exception === 'token_not_found' || exception === 'token_expired')) { | |
39 | promise = queue.pushRetryFn(exception, function retryRequest() { | |
40 | return $injector.get('$http')(originalResponse.config); | |
41 | }); | |
42 | } | |
43 | return promise; | |
44 | }); | |
45 | }; | |
46 | }]) | |
47 | .config(['$httpProvider', function($httpProvider) { | |
48 | $httpProvider.responseInterceptors.push('securityInterceptor'); | |
49 | }]) | |
50 | ||
51 | /* retryQueue.js */ | |
52 | angular.module('security.retryQueue', []) | |
53 | .factory('securityRetryQueue', ['$q', '$log', function($q, $log) { | |
54 | var retryQueue = []; | |
55 | var service = { | |
56 | // The security service puts its own handler in here! | |
57 | onItemAddedCallbacks: [], | |
58 | hasMore: function() { | |
59 | console.log('retryQueue.js -> hasMore: ' + retryQueue.length); | |
60 | return retryQueue.length > 0; | |
61 | }, | |
62 | push: function(retryItem) { | |
63 | retryQueue.push(retryItem); | |
64 | // Call all the onItemAdded callbacks | |
65 | angular.forEach(service.onItemAddedCallbacks, function(cb) { | |
66 | try { | |
67 | console.log('retryQueue.js -> push: ' + retryItem.reason); | |
68 | cb(retryItem); | |
69 | } catch(e) { | |
70 | $log.error('securityRetryQueue.push(retryItem): callback threw an error' + e); | |
71 | } | |
72 | }); | |
73 | }, | |
74 | pushRetryFn: function(reason, retryFn) { | |
75 | console.log('retryQueue.js -> pushRetryFn called'); | |
76 | console.log('retryQueue.js -> pushRetryFn reason: ' + reason); | |
77 | console.log('retryQueue.js -> pushRetryFn retryFn: ' + retryFn); | |
78 | // The reason parameter is optional | |
79 | console.log('retryQueue.js -> arguments: ' + arguments); | |
80 | console.log('retryQueue.js -> arguments: ' + arguments.length); | |
81 | if ( arguments.length === 1) { | |
82 | console.log('retryQueue.js -> reason in pushRetryFn: ' + reason); | |
83 | retryFn = reason; | |
84 | reason = undefined; | |
85 | } | |
86 | ||
87 | // The deferred object that will be resolved or rejected by calling retry or cancel | |
88 | var deferred = $q.defer(); | |
89 | var retryItem = { | |
90 | reason: reason, | |
91 | retry: function() { | |
92 | console.log('retryQueue.js -> pushRetryFn with reason ' + reason); | |
93 | // Wrap the result of the retryFn into a promise if it is not already | |
94 | $q.when(retryFn()).then(function(value) { | |
95 | console.log('retryQueue.js -> resolve pushRetryFn with retry and value: ' + value); | |
96 | // If it was successful then resolve our deferred | |
97 | deferred.resolve(value); | |
98 | }, function(value) { | |
99 | // Othewise reject it | |
100 | console.log('retryQueue.js -> reject pushRetryFn with reject and value: ' + value); | |
101 | deferred.reject(value); | |
102 | }); | |
103 | }, | |
104 | cancel: function() { | |
105 | // Give up on retrying and reject our deferred | |
106 | deferred.reject(); | |
107 | } | |
108 | }; | |
109 | console.log('retryQueue.js -> pushRetryFn push retryItem: ' + retryItem.reason); | |
110 | service.push(retryItem); | |
111 | return deferred.promise; | |
112 | }, | |
113 | retryReason: function() { | |
114 | return service.hasMore() && retryQueue[0].reason; | |
115 | }, | |
116 | cancelAll: function() { | |
117 | while(service.hasMore()) { | |
118 | retryQueue.shift().cancel(); | |
119 | } | |
120 | }, | |
121 | retryAll: function() { | |
122 | while(service.hasMore()) { | |
123 | retryQueue.shift().retry(); | |
124 | } | |
125 | } | |
126 | }; | |
127 | return service; | |
128 | }]); | |
129 | ||
130 | ||
131 | /* security.js */ | |
132 | angular.module('security.service', ['session.service', 'security.signin', 'security.retryQueue', 'security.tokens', 'ngCookies']) | |
133 | .factory('security', ['$location', 'securityRetryQueue', '$q', 'TokenHandler', '$cookieStore', 'Session', 'i18nNotifications', 'User', function($location, queue, $q, TokenHandler, $cookieStore, Session, i18nNotifications, User) { | |
134 | function redirect(url) { | |
135 | url = url || '/'; | |
136 | $location.path(url); | |
137 | } | |
138 | ||
139 | var skipRequests = false; | |
140 | ||
141 | // Register a handler for when an item is added to the retry queue | |
142 | queue.onItemAddedCallbacks.push(function(retryItem) { | |
143 | if ( queue.hasMore() ) { | |
144 | if(skipRequests) {return;} | |
145 | // make sure only one token is created by skiping subsequant authentication requests | |
146 | console.log('security.js -> set skipRequests to true'); | |
147 | skipRequests = true; | |
148 | if(retryItem.reason === 'token_expired') { | |
149 | service.refreshToken().then(function(result) { | |
150 | if(result) { | |
151 | var currentToken = TokenHandler.get(); | |
152 | console.log('security.js -> currentToken before queue.retryAll() call:' + currentToken); | |
153 | console.log('security.js -> result before queue.retryAll() call:' + currentToken); | |
154 | queue.retryAll(); | |
155 | } | |
156 | // user has to authorize with credentials | |
157 | else | |
158 | { | |
159 | service.signout(); | |
160 | } | |
161 | skipRequests = false; | |
162 | console.log('security.js -> set skipRequests to false'); | |
163 | }); | |
164 | } else { | |
165 | // user has to authorize with credentials | |
166 | skipRequests = false; | |
167 | console.log('security.js -> set skipRequests to false before signout'); | |
168 | service.signout(); | |
169 | } | |
170 | } | |
171 | }); | |
172 | ||
173 | var service = { | |
174 | // get a new valid token using the refresh token | |
175 | refreshToken: function() { | |
176 | console.log('security.js -> refreshToken called, d created'); | |
177 | var d = $q.defer(); | |
178 | var token = TokenHandler.getRefreshToken(); | |
179 | // cannot refresh token if not found on the client | |
180 | if(!token) { | |
181 | console.log('security.js -> token not found on a client'); | |
182 | d.resolve(false); | |
183 | } | |
184 | ||
185 | console.log('security.js -> token found on a client: ' + token); | |
186 | var session = new Session({ | |
187 | refreshToken: token | |
188 | }); | |
189 | ||
190 | console.log('security.js -> calling session.tokenRefresh'); | |
191 | session.tokenRefresh(function(result) { | |
192 | if(result) { | |
193 | console.log('security.js -> result OK, d.resolve(true), setting token with a accessToken: ' + result.accessToken + ' and refresh token: ' + result.refreshToken); | |
194 | d.resolve(true); | |
195 | TokenHandler.set(result); | |
196 | } else { | |
197 | console.log('security.js -> result NOT ok, d.resolve(false)'); | |
198 | d.resolve(false); | |
199 | } | |
200 | }); | |
201 | ||
202 | console.log('security.js -> returning d.promise'); | |
203 | return d.promise; | |
204 | } | |
205 | }; | |
206 | ||
207 | return service; | |
208 | }]); | |
209 | ||
210 | /* httpHeaders.js */ | |
211 | angular.module('services.httpHeaders', []) | |
212 | .factory('HttpHeaders', ['$injector', function($injector) { | |
213 | var http = $injector.get('$http'); | |
214 | var service = { | |
215 | initHeaders: function() { | |
216 | }, | |
217 | // set session token used to authorize the user against the api | |
218 | setAuthorizationToken: function(token) { | |
219 | console.log('httpHeaders.js -> setting authorization token: ' + token); | |
220 | http.defaults.headers.common['Authorization'] = 'Bearer ' + token; | |
221 | }, | |
222 | ||
223 | clearAuthorizationHeader: function() { | |
224 | http.defaults.headers.common['Authorization'] = null; | |
225 | } | |
226 | }; | |
227 | return service; | |
228 | }]); | |
229 | ||
230 | /* tokenHandler.js */ | |
231 | angular.module('security.tokens', ['ngResource']) | |
232 | .factory('TokenHandler', ['HttpHeaders', '$cookieStore', function(HttpHeaders, $cookieStore) { | |
233 | var token = null; | |
234 | ||
235 | function initToken() { | |
236 | if(!token) { | |
237 | token = $cookieStore.get('authorization-token'); | |
238 | } | |
239 | } | |
240 | ||
241 | var service = { | |
242 | // set a new token and save to cookies | |
243 | set: function(newToken) { | |
244 | token = newToken; | |
245 | $cookieStore.put('authorization-token', token); | |
246 | HttpHeaders.setAuthorizationToken(token.accessToken); | |
247 | }, | |
248 | ||
249 | // try to init the token from cookies | |
250 | init: function() { | |
251 | initToken(); | |
252 | if(!token) {return;} | |
253 | HttpHeaders.setAuthorizationToken(token.accessToken); | |
254 | }, | |
255 | ||
256 | // clear token and remove it from cookies | |
257 | clear: function() { | |
258 | $cookieStore.remove('authorization-token'); | |
259 | token = {}; | |
260 | HttpHeaders.clearAuthorizationHeader(); | |
261 | }, | |
262 | ||
263 | // return currently active token | |
264 | get: function() { | |
265 | initToken(); | |
266 | if(token) {return token.accessToken;} | |
267 | else {return null;} | |
268 | }, | |
269 | ||
270 | // return the refresth token | |
271 | getRefreshToken: function() { | |
272 | initToken(); | |
273 | if(token) { | |
274 | console.log('tokenHandler.js -> getRefreshToken: ' + token); | |
275 | return token.refreshToken; | |
276 | } | |
277 | else { | |
278 | console.log('token was not found, returning null'); | |
279 | return null; | |
280 | } | |
281 | } | |
282 | }; | |
283 | service.init(); | |
284 | return service; | |
285 | }]); |