I have an API with token based authentication mechanism. After successful signin I store two tokens in the browser's local storage - access and refresh token. The access token contains all necessary information required to authorize a user on the server side and it has expiration date. When the access token is expired the client could request a new access token using refresh token and in the response it will get a pair of new tokens.
In angular 1.x the implementation is pretty simple and straightforward. For instance we could use interceptors:
httpInterceptor.$inject = ['$httpProvider'];
function httpInterceptor($httpProvider) {
$httpProvider.interceptors.push(handleStaleAccessToken);
handleStaleAccessToken.$inject = ['$q', '$injector', 'session'];
function handleStaleAccessToken($q, $injector, session) {
function logoutAndRedirect() {
var authenticationRedirect = $injector.get('authenticationRedirect');
session.destroy();
authenticationRedirect.toLoginPage();
}
return {
responseError: function(rejection) {
// Do nothing for non 403 errors
if (rejection.status !== 403) {
return $q.reject(rejection);
}
var errorCode = rejection.data.error && rejection.data.error.code;
if (errorCode === 'access_token_expired') {
var $http = $injector.get('$http');
// Refresh token
var params = { refreshToken: session.getRefreshToken() };
return $http.post('/api/auth/refresh', params).then(function(response) {
session.setTokens(response.data);
// Re try failed http request
return $http(rejection.config);
}).catch(function(error) {
logoutAndRedirect();
return $q.reject(error);
});
} else {
logoutAndRedirect();
}
return $q.reject(rejection);
}
};
}
}
But how to implement similar logic in angular 2 / rxjs app?
I had to do something similar in my recent project shafihuzaib/cdp-ng-boilerplate and landed on this question for my answer. I couldn't go for the above suggested solution, as it felt complicated and something not desirable. So I came back to leave my solution after I implemented one. However, the difference being that in my case, I had two such tokens.
So, every request that needs to have tokens' validity checked, is called inside this function.
The most important thing here is that
func()
should return anObservable
, so that it can be consumed accordingly.It may seem a bit complicated for someone new, but I am sure it is a little more efficient.
In the following links, please ignore the details that are irrelevant to this question and focus on the usage of the suggested solution.
Actual implementation of
tokenValidatedRequest()
in my project.How it is used in other services!
How I finally subscribe to it!
This can be done transparently in Angular2 by extending the
Http
class and leveraging observable operators likeflatMap
.Here is some sample code:
This code must be integrated into a custom sub class of the
Http
one:An approach could be to extend the HTTP object to intercept errors:
and register it as described below:
For more details have a look at these questions: