Handling Authentication in Angular

Using Auth Interceptor

Pankaj Parkar
May 5, 2020 · 4 min read

Security is an important aspect of a system. To achieve the same we have to do a lot more than just log in authentication. Like authentication, authorization, data security, etc. We’re not going to cover each of them, but we will touch the part of it. Mainly authentication part.

Authentication can be implemented in web applications in multiple ways like session-based, cookie-based, token-based, etc. Our main focus would be looking at token-based authentication.

In token-based authentication, basically user login in into the system and server sends access_token and refresh_token with its expiry if the user is validated. This part is simple, a user enters into a web application. After a user gets logged in, each API call has to be validated to maintain the data security of an application. We have to send access_token with each request. On server-side API, it extracts access_token from the request, verifies (inside Identity Server) if it is valid or not based on its expiry. And return a data if a token is not expired, or return 401 status if access_token is expired.

We created services dedicated to making ajax calls. For authorization purposes, we’ve to ensure Auth Header is getting passed with each request.

Don’t you think that this is a code smell, like think you’re having this change in hundreds of service methods? This would violate the DRY (Don’t Repeat Yourself). We should find a better way to do this, maybe something that could help us to intercept the http request before/after it makes a call to Server.

Yes, HttpInterceptoris useful here to solve this problem. Basically it allows us to intercept http request / response and give access to manipulate it. Hence our generic logic to add header in the request can be kept here. Basic TokenInterceptor code may look like below.

In the above snippet, we have implements TokenInterceptorService class from HttpInterceptor a method. Then implemented an interceptor method that provides control to modify the request/response. Thus we have kept adding a token to header part in there.

app.module.ts

Extending HTTP_INTECEPTORS provider is needed to take TokenIntercetporService in action. This can be registered inside your app.module.ts

Ideally TokenInterceptor should take care of the below things.

  1. Add Authorization the header on each request
  2. Allow requests which don’t require token logic at all.
  3. If the token expires, then it automatically refreshes the token.

So far we have looked at the 1st part. Let’s go ahead and complete our TokenIntercptor implementation of the remaining points.

To allow requests which don’t require a token, that logic can be return like below

// You can also keep regx check to white no authenticate requestsif (whiteListUrls.find(w => request.url.includes(w))) {    return next.handle(this.addTokenToRequest(request, token));}

And then the update TokenInterceptorService will look like below

token-interceptor.ts

Generally access_token have 60 minutes expiry for security reasons. After 60 minutes token access_tokenbecome invalid and API could return a response with 401 status. To handle this case we’ve to make a new token using refresh_token and use that token for further API calls.

Well, do you think what we did enough? Did we really consider all the edge cases? No, not really. Think about what would happen, if authorized in user stays for a long time on the dashboard page. After an hour or so he navigates to the products page. In total products page have 10 calls. Since the user has stayed there on the dashboard page for an hour, the access_token had expired. So as soon as the user navigates to products page it should call refresh token API to retrieve a new token. As per current logic by checking expiry time internally refresh_token will happen and it will refresh the token.

But wait there is a catch. As soon as a user lands on the products page, it will make 10 ajax calls simultaneously. Thus all calls gonna fail and there will 10 refresh token calls will happen for each expired access_token . This is not right at all.

Let’s think about how can we handle this situation. When a user lands on the products page, all 10 calls suppose to expired access_token . We’ve to make sure that only 1st call out of 10 calls should retrieve new access_token , and all other 9 calls should wait until refreshToken API call finishes. As soon as it finishes other waited ajax call will resume. Pretty nice! Theoretically, we’ve solved the problem. Let’s see how can we implement it in interceptor code. Perhaps Subject observable could help us in queuing the calls who wait to refreshToken call to finish.

I’ve seen many implementations of refresh token logic in the interceptor. Most of the logic refreshes the token when any request fails and returns a 401 error. But over here we’ve first check expiry flag before making an ajax, I think which make sense

Conclusion:

We have learned how HttpInterceptor can be utilized to implement authentication in Angular application. There are also other cases where HttpInterceptor usage fits in as building retry failed ajax call mechanism, request/response massaging, generic API failure handling, etc. Remember you can write n number of HTTP interceptors that can kick in one after the other.

Deskera Engineering

Solving real world problems with loads of ingenuity and a dash of engineering