Reputation: 1393
I am struggling a little bit with handling 401 errors application wide.
Some other posts where not really helping me: Angularjs - handling 401's for entire app 401 unauthorized error handling in AngularJS
I have to send an authentication token, if it is defined on every request, thats why I need a request part in the Interceptor.
My current approach looks like:
module.factory('authInterceptor', function ($rootScope, $q, $window, $location) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
}
else{
console.log("authInterceptor: No Token to send")
}
return config;
},
response: function (response) {
if (response.status == 401) {
console.log("No Logged In");
$location.path('/login');
}
return response || $q.when(response);
},
responseError: function(rejection){
var defer = $q.defer();
if(rejection.status == 401){
console.log("401 Rejection");
console.dir(rejection);
}
defer.reject(rejection);
return defer.promise;
}
};
});
As far as my debugging goes if a 401 happens after request, it will be handled in the repsonse function. Which itself gives way a promise to the original caller.
If i comment out $q.when(response) and only return the repsonse there is no change.
Response is called even before the original caller gets .error
Thx for any ideas. Hopefully I am not to far away from a solution.
Upvotes: 2
Views: 3726
Reputation: 4321
If you have Devise in the stack; it's most likely failing because Warden takes precedence over anything else. The headers won't be inserted; even though you use a before_action
instead of after_action
.
Check out this question instead: ttp://stackoverflow.com/questions/11177079/how-to-send-cors-headers-with-devise-if-user-not-authorized-401-response
Upvotes: 0
Reputation: 23
@frankmt thanks a lot! Not enough rep to upvote or comment your solution, anyways it is exactly what I had missed. With Express and CORS it would be..
// THE CORS BLOCK HAS TO GO BEFORE THE JWT BLOCK
app.options('*', cors());
app.use(cors());
//protect routes with JWT - Token based auth
var secret = 'env.SECRET';
var publicPaths = [ '/apply', '/login'];
app.use('/', expressJwt({secret: secret}).unless({path: publicPaths}));
Upvotes: 0
Reputation: 133
I had the same issue, and in my case the problem was that I was adding the CORS headers as an after filter in the response, which meant that they weren't being sent when a 401 was issued.
Not sure what type of server you are using, but this is the rails version that works for me (changing it to a before_filter:
before_filter :allow_cors
def allow_cors
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS'
headers['Access-Control-Allow-Headers'] = 'Accept, Cache-Control, Referer, User-Agent, Origin, X-Requested-With, X-Prototype-Version, Content-Type, accept, autho
headers['Access-Control-Allow-Credentials'] = 'true'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Max-Age'] = '1728000'
end
(Clearly these are quite permissive settings, so please adjust them before using it in production)
They way I've managed to find this out was by testing the request locally with CURL, so this might help you:
curl -H "Origin: http://example.com" --verbose http://localhost:3000/
This way you will be able to see if the headers are being returned correctly even when the request is not authorized.
Upvotes: 2
Reputation: 14450
Your approach is good.
I think you don't need the "response" interceptor, only "request" to inject token and "responseError" to handle 401 response error :
return {
'responseError': function(response) {
if (response && response.status === 401) {
//DO WHAT YOU WANT HERE
console.log("There was a 401 error");
}
return $q.reject(response);
},
'request': function(config) {
config.headers = config.headers || {};
// ADD YOUR HEADER HERE
return config || $q.when(config);
}
};
Upvotes: 0