Auth Interceptor in Angular for JWT

Share this video with your friends

Send Tweet

Adding JWT support to the client. Storing the token in local storage, then creating a http interceptor to add the token to requests made to the server. Also implementing logout.

Marek
Marek
~ 10 years ago

may be little bit easier is use https://github.com/auth0/angular-jwt

Toby
Toby
~ 10 years ago

This is a little off-topic, but how are you getting all of the ng support within WebStorm? I noticed when you make you factories, it auto-completes much of the code for you. Is that something you did within WS? I'm using the Live Templates, but they behave the same way I'm seeing your stuff work.

Kent C. Dodds
Kent C. Dodds(instructor)
~ 10 years ago

Hi Toby, I actually don't believe I've done anything to get the auto-complete. All I can say is make sure that you're on the latest version of WebStorm. If that's not it, I'd just google around...

Kent C. Dodds
Kent C. Dodds(instructor)
~ 10 years ago

Seems like an awesome library :-) I don't think it was around at the time I made this lesson.

Martin
Martin
~ 9 years ago

From what I've read saving the token to local storage isn't the best solution, and instead it should be saved to a cookie (with SSL for production). Why is there a discrepancy in where different developers suggest storing the token?

Kent C. Dodds
Kent C. Dodds(instructor)
~ 9 years ago

From a security standpoint, it doesn't make a difference. The reason I chose not to store it as a cookie is because cookies are commonly used as a means to share data between the client and the server during requests. However, with the "new" architecture of having the client app and the api being served on different domains, that data sharing doesn't happen (clients don't send cookies to servers under a different domain including sub domains). Therefore I believe it's misleading to use cookies and choose local or session storage instead.

Martin
Martin
~ 9 years ago

Thanks Kent, that makes a lot of sense. Cheers

Martin
Martin
~ 9 years ago

Hi Kent, sorry one more question. I've also read about using a refresh token (or single request token) that produces a single use token to reduce the window of attack if a token is compromised, as it's only valid for the single request. Is this something you consider in your applications? and from the current video how would this change the implementation. Seems like you could do it by adding a response to the interceptor that used the AuthTokenFactory. If knowing something about the application I'm working on helps I'm building an Ionic application with a Laravel 5.1 API.

Kent C. Dodds
Kent C. Dodds(instructor)
~ 9 years ago

I don't think there's anything wrong with that. The interceptor hides the complexity away from the rest of your app so you don't need to think about it at all.

I've never done this before, but I'd be concerned about timing issues. Like, what if I send several requests at once and the server sends response A before response B, so response B's token is the one that needs to be used next, but then response B gets to the client first and response A's token overrides B's token. I'm not sure how likely that is to occur, and like I said I've never tried this kind of an architecture, but I'd be concerned about that.

Just as a tip. As far as I'm aware, most web applications are using cookies or localStorage with a token that lasts the duration of the logged in session. This is no less secure than cookies. In either case, if someone gets ahold of the machine, they can look right at the cookie/token and use it to make requests. What you've suggested would help alleviate that concern only if that individual weren't able to get the next valid token from your server, which is unlikely. So I don't really see what this approach buys you...

Matheus
Matheus
~ 9 years ago

Hi Kent, thanks for the video it was awesome. About this topic I'm actually reading a lot to further understand the security discussion and from what I read I think that it still scares me a little bit using the localStorage because of possible XSS.

A malicious script (not necessary unsanitized from the end-user; it could be from a CDN compromised script) could get the JWT of a bunch of clients using this technique. Using an HTTP only SSL cookie would have the advantage of not allowing this kind of hijacking, however, now you have to worry about CSRF, and that sucks as well.

OWASP Top 10 list puts XSS before CSRF so I'm guessing this problem is harder to spot and mitigate the risks.

What is your opinion on that? I'm being completely honest with you in that I don't know what's the next step to take as I already have an Mobile App running on Windows Azure Mobile Services and now that we're implementing also a Web Client our team is having these kind of concerns.

Thanks a lot once again.

Kent C. Dodds
Kent C. Dodds(instructor)
~ 9 years ago

I think, like with all technology, you have to make certain trade-offs. If you're concerned about a compromised script from a CDN hijacking your users and stealing tokens, then don't use a CDN you don't trust. You could potentially store the token in a cookie if you want to. But I'm not certain that you'd be able to access it.

Nate Gibbons
Nate Gibbons
~ 9 years ago

Here's a great article with a run-down on the security trade-offs for either storage solution:

https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

Juan
Juan
~ 9 years ago

Any samples on how to create the cookie alternative?

Juan
Juan
~ 9 years ago

A video series explaining the two alternatives would be great (tokens in local storage VS cookies for storage)

Kent C. Dodds
Kent C. Dodds(instructor)
~ 9 years ago

It's pretty much just a matter of changing the AuthTokenFactory to utilize the Cookie API rather than the LocalStorage API.

Tony
Tony
~ 9 years ago

Kent,

My project's code is split out such that the controllers are within different files as is the factory. This method has been working well for me... until I try to add the Auth Interceptor. I have a module('report') to which I am trying to add the interceptor. I have tried the below, but while I get no error, the function also doesn't get called.

My question is, how to I inject the code defined in the jwt.js file (below) into the module after the module has been defined in my app.js rather than lumping all the code into a huge jumbled js file.

angular.module('report') .requires.push.apply(angular.module('report'), ['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor'); }]);

The jwt.js file:

(function () {

angular
    .module('report')
    .factory('AuthInterceptor', function (API, auth) {
        return {
            // automatically attach Authorization header
            request: addToken
        };
        function addToken (config) {
            var token = jwt.getToken();
            
            if (token) {
                config.headers = config.headers || {};
                config.headers.Authorization = 'Bearer ' + token;
            }
            return config;
        }
    })
    .factory('jwt', function ($window, $q) {
        var store = $window.localStorage,
            key = 'auth-token',
            dev = $q.defer();
    
        return {
            setToken: setToken,
            getToken: getToken
        };
    
        function setToken (token) {
            if (token) {
                store.setItem(key, token);
            } else {
                store.removeItem(key);
            }
        }
    
        function getToken () {
            return store.getItem(key);
        }
    });

})();

Cary
Cary
~ 8 years ago

In the video you say we usually hide the secret key in some where backend to keep it private,can you show me what to do to achieve that?