JWT with SPA without a server - javascript

The application is a SPA that is hosted on static storage (conceptually similar to S3, although it's not S3) and has no backend server at all. Assume this is https://static.example.com/app.html
When users visit the page, they can authenticate with an external provider like Auth0 and Azure AD. They complete the authentication flow and are sent back to the SPA with an id_token on the URL fragment. For example, https://static.example.com/app.html#id_token=XX. That id_token is used to call an external API server, passed in the Bearer authorization header.
The issue is where to store the JWT in the client.
It's a known fact that storing the JWT in sessionStorage could lead to the tokens being stolen with XSS attacks (or malicious code added in a dependency, etc).
The recommended approach would be storing the JWT in a cookie that is set to HttpOnly, or at least part of it (see the "Cookie Split" section). However, this is not doable in my case, as there is no backend server, and after being authenticated users are redirected to the SPA directly, so I can't create a HttpOnly cookie. A variant of this method is what OWASP recommends: using a "fingerprint cookie". This has the same issues since I can't set a cookie that is HttpOnly.
Another approach, as for example suggested by the Auth0 documentation, is to keep the JWT in memory. While this should prevent theft with most (if not all?) XSS attacks, it's unpractical because the session would be limited to the current tab, and would not survive a page reload.
I see two different options, all with serious or potentially serious drawbacks:
Store the token in sessionStorage anyways, assuming the risk that in case of XSS attacks (or a malicious dependency injected via NPM) could lead to sessions being stolen. This could be mitigated by setting a short lifespan to tokens (e.g. 1 hour). While the app I'm working on doesn't store critical information (it's not banking or similar), a mistake in the code that let sessions to be stolen via XSS would not be nice.
Implement a backend server to move the authentication flow there, maybe even replacing JWT's with session tokens entirely. This would make the application not static anymore, however, and it's undesirable.
(The third option, keeping the JWT in memory, is excluded because of the poor user experience)
What am I missing?

Security is a compromise - you can choose to accept the risk of XSS, or to take the burden of a backend server for more security, or to sacrifice user experience for a level of security probably inbetween the two. You can't have everything.
One usual solution is to have very short-lived tokens in sessionStorage, and an httpOnly cookie for the identity provider to get a new token when needed. This way stealing a session token provides less value for the attacker, and as XSS needs user interaction, it may sometimes be difficult for an attacker to get hold of a new one (or easy, depending on where the XSS is). Also this solution needs more graceful error-handling and results in slightly more complex code.

Related

Where and how save token JWT ? (Best Practice)

I've read that save token JWT in localStorage is a bad practice.
https://dev.to/rdegges/please-stop-using-local-storage-1i04
I'm working with ReactJs, and to other side have a API Rest with NodeJs.
Where and how I should save token JWT ?, in a Cookie?
Gretting from Chile,
If the choice is between cookie and localStorage, both have their pros and cons when it comes to security. With all security attributes set correctly (HttpOnly, secure, SameSite=strict) it is true that a cookies could be more protected against certain attacks.
However, SameSite attributes may not work for everyone, and may not protect all functions against CSRF (Cross Site Request Forgery) attacks.
HttpOnly will protect the value from being accessed from JavaScript which is good if the application suffers (XSS) Cross Site Scripting vulnerabilities. However, any moderately qualified attacker could easily achieve what they wanted without accessing the actual value of the token anyway.
The thing to remember when storing tokens in localStorage is that it is not cleared when the browser is closed, meaning that a user will not become logged out by closing the browser - which many have come to expect. If that is a problem, you may want to consider storing the JWT in the sessionStorage instead.
localStorage seems fine because many people are using localStorage.
If you want extra security feature
You can make your token lifespan short eg {30 min, 60 min}
Also You can check your user active state whether or not
The user will Logout automatically

Is it safe to store a JWT in localStorage with ReactJS?

I'm currently building a single page application using ReactJS.
I read that one of the reasons for not using localStorage is because of XSS vulnerabilities.
Since React escapes all user input, would it now be safe to use localStorage?
In most of the modern single page applications, we indeed have to store the token somewhere on the client side (most common use case - to keep the user logged in after a page refresh).
There are a total of 2 options available: Web Storage (session storage, local storage) and a client side cookie. Both options are widely used, but this doesn't mean they are very secure.
Tom Abbott summarizes well the JWT sessionStorage and localStorage security:
Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks. XSS, in a nutshell, is a type of vulnerability where an attacker can inject JavaScript that will run on your page. Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts <script>alert('You are Hacked');</script> into a form to see if it is run by the browser and can be viewed by other users.
To prevent XSS, the common response is to escape and encode all untrusted data. React (mostly) does that for you! Here's a great discussion about how much XSS vulnerability protection is React responsible for.
But that doesn't cover all possible vulnerabilities! Another potential threat is the usage of JavaScript hosted on CDNs or outside infrastructure.
Here's Tom again:
Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads. We use package managers like Bower to import other peoples’ code into our apps.
What if only one of the scripts you use is compromised? Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their knowledge. This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage. This includes session identifiers and tokens.
Therefore, my conclusion is that as a storage mechanism, Web Storage does not enforce any secure standards during transfer. Whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP.
Basically it's OK to store your JWT in your localStorage.
And I think this is a good way.
If we are talking about XSS, XSS using CDN, it's also a potential risk of getting your client's login/pass as well. Storing data in local storage will prevent CSRF attacks at least.
You need to be aware of both and choose what you want. Both attacks it's not all you are need to be aware of, just remember: YOUR ENTIRE APP IS ONLY AS SECURE AS THE LEAST SECURE POINT OF YOUR APP.
Once again storing is OK, be vulnerable to XSS, CSRF,... isn't
I know this is an old question but according what #mikejones1477 said, modern front end libraries and frameworks escape the text giving you protection against XSS. The reason why cookies are not a secure method using credentials is that cookies doesn't prevent CSRF when localStorage does (also remember that cookies are accessible by JavaScript too, so XSS isn't the big problem here), this answer resume why.
The reason storing an authentication token in local storage and manually adding it to each request protects against CSRF is that key word: manual. Since the browser is not automatically sending that auth token, if I visit evil.example and it manages to send a POST http://example.com/delete-my-account, it will not be able to send my authn token, so the request is ignored.
Of course httpOnly is the holy grail but you can't access from reactjs or any js framework beside you still have CSRF vulnerability. My recommendation would be localstorage or if you want to use cookies make sure implemeting some solution to your CSRF problem like Django does.
Regarding with the CDN's make sure you're not using some weird CDN, for example CDN like Google or bootstrap provide, are maintained by the community and doesn't contain malicious code, if you are not sure, you're free to review.
A way to look at this is to consider the level of risk or harm.
Are you building an app with no users, POC/MVP? Are you a startup who needs to get to market and test your app quickly? If yes, I would probably just implement the simplest solution and maintain focus on finding product-market-fit. Use localStorage as its often easier to implement.
Are you building a v2 of an app with many daily active users or an app that people/businesses are heavily dependent on. Would getting hacked mean little or no room for recovery? If so, I would take a long hard look at your dependencies and consider storing token information in an http-only cookie.
Using both localStorage and cookie/session storage have their own pros and cons.
As stated by first answer: If your application has an XSS vulnerability, neither will protect your user. Since most modern applications have a dozen or more different dependencies, it becomes increasingly difficult to guarantee that one of your application's dependencies is not XSS vulnerable.
If your application does have an XSS vulnerability and a hacker has been able to exploit it, the hacker will be able to perform actions on behalf of your user. The hacker can perform GET/POST requests by retrieving token from localStorage or can perform POST requests if token is stored in a http-only cookie.
The only down-side of the storing your token in local storage is the hacker will be able to read your token.
One thing to keep in mind is whether the JWTs are:
First party (ie. simply for accessing your own server commands)
Third party (ie. a JWT for Google, Facebook, Twitter, etc.)
If the JWT is first-party:
Then it doesn't matter that much whether you store the JWT in local storage, or a secured cookie (ie. HttpOnly, SameSite=strict, and secure) [assuming your site is already using HTTPS, which it should].
This is because, assuming an XSS attack succeeds (ie. an attacker was able to insert Javascript code through a JS dependency that is now running on all visitor browsers), it's "game over" anyway; all the commands which were meant to be secured by the "JWT token verifications", can now be executed by the attacker just by having the script they've inserted into the frontend JS call all the needed endpoints. Even though they can't read the JWT token itself (because of the cookie's http-only flag), it doesn't matter because they can just send all the needed commands, and the browser will happily send the JWT token along with those commands.
Now while the XSS-attack situation is arguably "game over" either way (whether local-storage or secured cookie), cookies are still a little better, because the attacker is only able to execute the attacks if/when the user has the website open in their browser.
This causes the following "annoyances" for the attacker:
"My XSS injection worked! Okay, time to collect private data on my boss and use it as blackmail. Dang it! He only ever logs in while I'm here at work. I'll have to prepare all my code ahead of time, and have it run within the three minutes he's on there, rather than getting to poke around into his data on the platform in a more gradual/exploratory way."
"My XSS injection worked! Now I can change the code to send all Bitcoin transfers to me instead! I don't have any particular target in mind, so I don't need to wait for anyone. Man though, I wish I could access the JWT token itself -- that way I could silently collect them all, then empty everyone's wallets all at once. With these cookie-protected JWTs, I may only be able to hijack a few dozen visitors before the devs find out and suspend transfers..."
"My XSS injection worked! This'll give me access to even the data that only the admins can see. Hmmm, unfortunately I have to do everything through the user's browser. I'm not sure there's a realistic way for me to download those 3gb files using this; I start the download, but there are memory issues, and the user always closes the site before it's done! Also, I'm concerned that client-side retransfers of this size might get detected by someone."
If the JWT is third-party:
In this case, it really depends on what the third-party JWTs allow the holder to do.
If all they do is let someone "access basic profile information" on each user, then it's not that bad if attackers can access it; some emails may leak, but the attacker could probably get that anyway by navigating to the user's "account page" where that data is shown in the UI. (having the JWT token just lets them avoid the "annoyances" listed in the previous section)
If, instead, the third-party JWTs let you do more substantial things -- such as have full access to their cloud-storage data, send out messages on third-party platforms, read private messages on third-party platforms, etc, then having access to the JWTs is indeed substantially worse than just being able to "send authenticated commands".
This is because, when the attacker can't access the actual JWT, they have to route all commands through your 1st-party server. This has the following advantages:
Limited commands: Because all the commands are going through your server, attackers can only execute the subset of commands that your server was built to handle. For example, if your server only ever reads/writes from a specific folder in a user's cloud storage, then the attacker has the same limitation.
Easier detection: Because all the commands are going through your server, you may be able to notice (through logs, sudden uptick in commands, etc.) that someone has developed an XSS attack. This lets you potentially patch it more quickly. (if they had the JWTs themselves, they could silently be making calls to the 3rd-party platforms, without having to contact your servers at all)
More ways to identify the attacker: Because the commands are going through your server, you know exactly when the commands are being made, and what ip-address is being used to make them. In some cases, this could help you identify who is doing the attacks. The ip-address is the most obvious way, though admittedly most attackers capable of XSS attacks would be aware enough to use a proxy.
A more advanced identification approach might be to, say, have a special message pop up that is unique for each user (or, at least, split into buckets), of such a nature that the attacker (when he loads up the website from his own account) will see that message, and try to run a new command based on it. For example, you could link to a "fake developer blog post" talking about some "new API" you're introducing, which allows users to access even more of their private data; the sneaky part is that the URL for that "new API" is different per user viewing the blog post, such that when the API is attempted to be used (against the victim), you know exactly who did it. Of course, this relies on the idea that the attacker has a "real account" on the site alongside the victim, and could be tempted/fooled by this sort of approach (eg. it won't work if the attacker knows you're onto him), but it's an example of things you can do when you can intercept all authenticated commands.
More flexible controlling: Lets say that you've just discovered that someone deployed an XSS attack on your site.
If the attackers have the 3rd-party JWTs themselves, your options are limited: you have to globally disable/reset your OAuth/JWT configuration for all 3rd-party platforms. This causes serious disruption while you try to figure out the source of the XSS attack, as no one is able to access anything from those 3rd-party platforms. (including your own server, since the JWT tokens it may have stored are now invalid)
If the JWT tokens are instead protected in http-only cookies, you have more options: You can simply modify your server to "filter out" any reads/writes that are potentially dangerous. In some cases added this "filtering" is a quick and easy process, allowing your site to continue in "read-only"/"limited" mode without disrupting everything; in other cases, things may be complex enough that it's not worth trusting the filter code for security. The point though is that you have more options.
For example, maybe you don't know for sure that someone has deployed an XSS attack, but you suspect it. In this case, you may not want to invalidate the JWT tokens of every user (including those your server is using in the background) simply on the suspicion of an XSS attack (it depends on your suspicion level). Instead, you can just "make things read-only for a while" while you look into the issue more closely. If it turns out nothing is wrong, you can just flip a switch and re-enable writes, without everyone having to log back in and such.
Anyway, because of these four benefits, I've decided to always store third-party JWTs in "secured cookies" rather than local storage. While currently the third-party JWTs have very limited scopes (such that it's not so big a deal if they are stolen), it's good future-proofing to do this, in case I'd like my app to request access to more privileged functionalities in the future (eg. access to the user's cloud storage).
Note: The four benefits above (for storing third-party JWTs in secured cookies) may also partially apply for first-party JWTs, if the JWTs are used as authentication by multiple backend services, and the domains/ip-addresses of these other servers/services are public knowledge. In this case, they are "equivalent to third-party platforms", in the sense that "http-only cookies" restrict the XSS attacker from sending direct commands to those other servers, bringing part of the benefits of the four points above. (it's not exactly the same, since you do at least control those other servers, so you can activate read-only mode for them and such -- but it'll still generally be more work than making those changes in just one place)
I’m disturbed by all the answers that suggest not to store in local storage as this is susceptible to an XSS attack or a malicious library. Some of these even go into long-winded discussions, even though the answer is pretty small/straightforward, which I’ll get to shortly.
Suggesting that is the equivalent of saying “Don’t use a frying pan to cook your food because if you end up drunk one night and decide to fry, you’ll end up burning yourself and your house”.
If the jwt gets leaked due to an XSS attack or malicious library, then the site owner has a bigger problem: their site is susceptible to XSS attacks or is using a malicious library.
The answer: if you’re confident your site doesn’t have those vulnerabilities, go for it.
Ref: https://auth0.com/docs/security/data-security/token-storage#browser-local-storage-scenarios
It is not safe if you use CDN's:
Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their knowledge. This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage. This includes session identifiers and tokens.
via stormpath
Any script you require from the outside could potentially be compromised and could grab any JWTS from your client's storage and send personal data back to the attacker's server.
Localstorage is designed to be accessible by javascript, so it doesn't provide any XSS protection. As mentioned in other answers, there is a bunch of possible ways to do an XSS attack, from which localstorage is not protected by default.
However, cookies have security flags which protect from XSS and CSRF attacks. HttpOnly flag prevents client side javascript from accessing the cookie, Secure flag only allows the browser to transfer the cookie through ssl, and SameSite flag ensures that the cookie is sent only to the origin. Although I just checked and SameSite is currently supported only in Opera and Chrome, so to protect from CSRF it's better to use other strategies. For example, sending an encrypted token in another cookie with some public user data.
So cookies are a more secure choice for storing authentication data.
Isn't neither localStorage or httpOnly cookie acceptable? In regards to a compromised 3rd party library, the only solution I know of that will reduce / prevent sensitive information from being stolen would be enforced Subresource Integrity.
Subresource Integrity (SRI) is a security feature that enables
browsers to verify that resources they fetch (for example, from a CDN)
are delivered without unexpected manipulation. It works by allowing
you to provide a cryptographic hash that a fetched resource must
match.
As long as the compromised 3rd party library is active on your website, a keylogger can start collecting info like username, password, and whatever else you input into the site.
An httpOnly cookie will prevent access from another computer but will do nothing to prevent the hacker from manipulating the user's computer.
There's a useful article written by Dr. Philippe De Ryck which gives an insight into the true impact of vulnerabilities particularly XSS.
This article is an eye opener!
In a nutshell, primary concern of the developer should be to protect the web application against XSS and shouldn't worry too much about what type of storage area is used.
Dr. Phillipe recommends the following 3 steps:
Don't worry too much about the storage area. Saving an access token in localStorage area will save the developer a massive amount of time for development of next phases of the application.
Review your app for XSS vulnerabilities. Perform a through code review and learn how to avoid XSS within the scope of your templating framework.
Build a defense-in-depth mechanism against XSS. Learn how you could further lock down your application. E.g. utilising Content Security Policy (CSP) and HTML5 sandboxing.
Remember that once you're vulnerable to XSS then its game over!
TLDR;
Both work, but using a cookie with httpOnly is way safer than using localStorage, as any malicious javascript code introduced by XSS can read localstorage.
I'm coming late to the discussion, but with the advantage of more mature and modern auth protocols like OpenID Connect.
TL;DR: The preferred method is to store your JWT Token in memory: not in a cookie, and not in localstorage.
Details
You want to decouple the responsibility of authenticating users from the rest of the work your app does. Auth is hard to get right, and the handful of teams that spend all their time thinking about this stuff can worry about the details you and I will never get right.
Establish a dedicated Identity Provider for your app, and use the OpenID Connect protocol to authenticate with it. This could be a provider like Google, Microsoft, or Okta, or it could be a lightweight Identity Server that federates to one or more of those other services.
Use the Authorization Code Flow to let the user authenticate and get the access token to your app. Use a respected client library to handle the OpenID Connect details, so you can just have the library notify your app when it has a valid token, when a new valid token has been obtained via refresh, or when the token cannot be refreshed (so the user needs to authenticate again). The library should be configured (probably by default) to avoid storing the token at all.
FAQ
What happens when someone refreshes the page? I don't want to make them log in again.
When the app first loads, it should always redirect the user to your Identity Provider. Based on how that identity provider handles things, there's a good chance the user won't have to log in. For example, if you're federating to an identity provider like Google or Microsoft, the user may have selected an option indicating that they are on a trusted device and they want to be remembered. If so, they won't need to log in again for a very long time, long after your auth token would have expired. This is much more convenient for your users.
Then again, if the user indicated they're on a shared device and shouldn't automatically be logged in in the future, you want to force another login: you cannot differentiate between someone who refreshed their browser window and someone who reopened a closed browser and navigated to a page stored in the browser's history.
Isn't the Identity Provider using cookies to keep the user logged in? What about CSRF or XSS attacks there?
Those implementation details are specific to the Identity Provider. If they're using cookies, it's their job to implement Anti-CSRF measures. They are far less likely than you are to use problematic third-party libraries, or import compromised external components, because their app only has one job.
Shouldn't I spend my time addressing XSS attacks instead? Isn't it "game over" if someone injects code into my app?
If it's an either/or proposition, and you have reason to believe your app has XSS or Code Injection vulnerabilities, then those should definitely take precedence. But good security involves following best-practices at multiple levels, for a kind of layered security.
Plus, using a trusted third-party library to connect to trusted third-party security providers should hopefully save you time that you would have spent dealing with a variety of other security-related issues.
It is safe to store your token in localStorage as long as you encrypt it. Below is a compressed code snippet showing one of many ways you can do it.
import SimpleCrypto from 'simple-crypto-js';
const saveToken = (token = '') => {
const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
const encryptedToken = encryptInit.encrypt(token);
localStorage.setItem('token', encryptedToken);
}
Then, before using your token decrypt it using PRIVATE_KEY_STORED_IN_ENV_FILE

JWT stateless sign-on with secure cookie storage : how to implement log out?

I am starting to implement a JWT based Single Sign On system (for several single page apps under the same domain, so something like app1.mydomain.com, app2.mydomain.com, auth.mydomain.com) using the mechanisms described in this article from Stormpath.
In order to protect my signed JWT token from XSS attacks, I want to store the token in a secure (HTTPS only) and HTTP-only cookie. The SPA itself will get the user info from the response body.
My main question is how can we implement a "log out" feature in JavaScript, since the cookie is, by design, not accessible from the JS code?
I am guessing that I will have to make a server call that will expire the cookie. Is there a pure-client-side way to do it though?
The best way would be to do the cleanup server-side as user JEY already suggested.
Additionally, I wanted to extend the bit on the possibilities so this did not fit a comment.
When dealing with browser-based applications selecting the token storage is almost a pick your poison game. If you go with a secure HTTP-only cookie you don't have to worry about XSS vulnerabilities leading to token disclosure. However, you'll still have to ensure you're not vulnerable to XSS by an whole set of another reasons.
This means you don't save any actual work, you just get that fuzzy feeling that if you do get compromised by XSS at least the token is safe.
On the other hand, by going with a cookie, CSRF is now something that needs to be on your radar and here is where things may get funny, some trivial methods of preventing CSRF like double-submit cookies can be implemented in such ways that they are virtually useless in the presence of exploitable XSS vulnerabilities in child domains for example.
I'm not saying that storing tokens in cookies is plain wrong, it isn't, likewise storing them in Web storage is also acceptable. In both cases you need to understand the consequences of your choice and the possibilities each one brings.
In this case, Web storage would simplify your logout scenario from a client-side perspective so you need to ask yourself which set of pros and cons are better suited for your scenario.
Given you mentioned multiple applications in child domains one thing to be aware of is the following:
With token-based auth, you are given the choice of where to store the JWT. Commonly, the JWT is placed in the browsers local storage and this works well for most use cases. There are some issues with storing JWTs in local storage to be aware of. Unlike cookies, local storage is sandboxed to a specific domain and its data cannot be accessed by any other domain including sub-domains.
(emphasis is mine, source: Where to Store Tokens? section of Cookies vs Tokens: The Definitive Guide)
(Disclosure: I'm an Auth0 engineer.)

JWT tokens in sessionStorage vs cookies?

There are a lot of blog posts from Stormpath that talk about how you ought to use cookies to store your JWT instead of sessionStorage/localStorage:
https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
https://stormpath.com/blog/token-auth-spa
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts
The main stated reason is that if a 3rd-party javascript dependency that you load is compromised that it can pilfer through sessionStorage/localStorage and transmit off the JWT to somewhere.
But this is confusing as a reason to me. I understand the attack vector, but if you have a compromised 3rd-party javascript dependency, aren't you effectively screwed anyway, since it can listen-in/capture anything your users do as they interact with your app?
I'm the author of https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
When XSS exist on a page, an attacker is privileged to:
HTML5 web storage (local and session)
Cookies that are not set with httpOnly flag
Control of the tab until it is closed and the ability to make unauthorized requests
You can also start to formulate attacks to get around XSRF protection.
When an XSRF vulnerability exists, an attacker is privileged to:
Making unauthorized requests from a 3rd party domain, if you can lure a user there (or send them there in the presence of XSS).
You can see that when an XSS vulnerability exists, you are able to make unauthorized requests and an attacker would need to jump through some more hoops to exploit XSRF. This means that when XSS exists (regardless of XSRF protection or not), the attack vector of making unauthorized requests will exist.
Hopefully, that clears things up for my next point.
An XSRF attacks or unauthorized requests has less impact and scope than stealing a stateless token that represents the user's identity and session. Leaking the token means that an attacker will have full control to formulate an attack on behalf of the user, on his time, on his machines.
In conclusion, in presence of XSS when you:
store an access token in web storage, the tokens for any user that uses your site during the time of the existence of XSS is compromised. This means an attacker could get thousands of valid access tokens and can possibly do a lot of harm (even more if you store refresh tokens in web storage). The users are also vulnerable to making unauthorized requests from their own browser.
store an access token in a httpOnly cookie, the tokens for any user are not compromised. But, the users are also vulnerable to making unauthorized requests from their own browser even in the presence of XSRF protection.
Hope this information helps.

AngularJS security on authentication

We're developing a system using AngularJS and PHP. I have some concerns about the security on the matter of authentication. I wrote a basic authentication based upon multiple different examples around the web (I only started learning Angular), which uses a database via REST API calls. On some routes it checks if the user information exists before it creates a promise, but I have a few questions:
Can session information be stored in$window.sessionStorage or $cookieStorage without the client being able to modify these values or should I keep them server-side with PHP $_SESSION and fetch them from there, never storing them anywhere in JS? Session information can contain uid, role, email and name
Can I store a value, like let's say $rootScope.role or $scope.role without the client being able to modify this value? Let's say for example we have multiple levels of user accounts where super-admin is the highest. If I create a route with a resolve which would check the $rootScope.rolelevel, can a novice go change the $rootScope.role value to super-admin gaining access to restricted backend sections?
Will I have to implement a GET /session check on every route to which gets $_SESSION data to actually make sure this data stays untouched?
Or am I just paranoid?
You're not paranoid, any client-side authentication should be questioned. When it comes to security, you can't assume that the client is forbidden or unable to do anything on their own device.
Security related functions must stay on the backend, an environment you set up and control.
can a novice go change the $rootScope.role value to super-admin gaining access to restricted backend sections?
Asking questions like "can a novice..." are futile in my opinion. Do you only want security against novice malicious users? If your "restricted backend sections" can be accessed by modifying the frontend, you're doing something wrong.
Great question! Front end security requires the cooperation of the browser and your server.
Javascript is an untrusted environment, so you can’t reliably enforce any authorization there (i.e. you can’t use properties on $scope to prevent a user from doing something). Your server needs to enforce these rules by ensuring that every API request is properly authenticated and authorized.
API requests are typically authenticated with a cookie. The cookie typically contains a session identifier, which points to a row in your database which contains the authorization information (i.e. what the user is allowed to access). The user can get this cookie by logging in (presenting hard credentials like a username and password).
The cookie may also contain a signed access token, such as a JWT. Depending on your architecture you can remove the session database and rely purely on the signed token for authentication.
In either case you want to set the HttpOnly flag on the cookie when your server is sending the cookie to the browser. This will prevent the JavaScript environment from reading the cookie, this is a good security measure to yourself against XSS attacks.
You also need to protect yourself against CSRF attacks. This is a situation where another website can trigger a GET or POST request to your API, and this will send along the authentication cookies. You can guard against this by creating another cookie that does NOT have the HttpOnly flag, and storing a random value in it. The JS environment must attach this value to any request, typically as a custom HTTP header. Your server then asserts that the value is associated with the session or token.
I’ve tried to cover all the bases in this answer. If you’d like to read more, you can check out these blog posts that I’ve written, they discuss token authentication, but each has sections that cover front-end security issues:
Token Based Authentication for Single Page Apps (SPAs)
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts/
Disclaimer: I work at Stormpath and we provide a secure, hosted user management solution for any application, including Angular! See https://docs.stormpath.com to learn more and find the SDK for your server.

Categories