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.
may be little bit easier is use https://github.com/auth0/angular-jwt
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.
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...
Seems like an awesome library :-) I don't think it was around at the time I made this lesson.
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?
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.
Thanks Kent, that makes a lot of sense. Cheers
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.
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...
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.
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.
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/
Any samples on how to create the cookie alternative?
A video series explaining the two alternatives would be great (tokens in local storage VS cookies for storage)
It's pretty much just a matter of changing the AuthTokenFactory
to utilize the Cookie API rather than the LocalStorage API.
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');
}]);
(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);
}
});
})();
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?