Using JWT instead of Cookie on SSL enabled site - security

Instead of using a cookie I'm using a JWT token which gets send with every request. Every request is a POST request so that the token does not get saved in the browser's history.
It's a single-page app.
The token looks like:
{
userId: 12345678,
expires: <UNIX timestamp>,
otherInfo: <something>
}
Everything is SSL secured.
The token is created on the server when the user logs on.
Would this be a good way to replace a cookie or do you see any flaws?

No, this is not a good solution. Using cookies (with a httpOnly flag) for cross-request persistence is not optional - it's the only way to safely store session credentials, in such a way that on-page JavaScript code cannot access it directly.
This is essential to prevent eg. session stealing in an XSS attack, by ensuring that scripts cannot access the credentials, but they can still be used in requests to the server.
Your use of JWT doesn't seem to really solve a problem, either - why can't you just use session cookies using an existing session implementation? This kind of thing is precisely is what they're made for.

Related

Is CSRF middleware needed if HTTPOnly cookie is used? And should it be session-based?

Now authorization sheme looks like this:
If the user input the correct data, the server generates a unique sessionKey, inserts it into the session table with FK for this user. In response to a JSON request, I send this sessionKey. The web client sets this key it in a cookie.
But the problem is that if the web client stores this cookie, JS will have access to them, and it is not safe.
The alternative is to set the HTTP-Only cookie. But it is not clear whether it is necessary to use CSRF middleware in this case. Does the HTTPOnly attribute solve the problem of XSS / CSRF attacks? If it does not decide and you need a CSRF middleware, then the csrf cookie must be a session cookie.
The problem is that all the csrf middlewares for my framework do not allow to use of the session csrf cookie. Alternatively, write my own middleware.
Do I understand correctly that the csrf middleware stores the token that I gave to the client in RAM and verifies on every request? But then what's the point of this token if it can be intercepted in the same way as an authorization cookie?
Let's start with stating that Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF) are two different animals.
XSS is about embedding malicious code into a site to have it executed on the client machine. No HTTPOnly flag can mitigate this.
CSRF is about embedding malicious code on some third party site and sending you the link to the third party site. The malicious code can try to fire GET/POST request (which can bypass browsers Same Origin Policy) and execute some unwanted actions on the site the user is logged to. It's easier to understand this with an example:
You are logged into your site on https://example.com. You are authenticated with a cookie.
Someone sends you a link to https://malicious.net. You open the link in a separate browser tab.
Malicious code is being executed and fires a request to https://example.com/deleteAccount=1. Cookie will be attached, request will be authenticated and executed.
The answer is no - the HTTPOnly flag will not mitigate any of this. But let us concentrate on solving CSRF issue. What options do you have?
In fact you have many: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
IMO the easiest could be passing the sessionKey not over a cookie, but over an Authorization header. This can not be done automatically by the browser so you would be safe from CSRF attacks.

httpOnly cookies with React and Node

I'm trying to figure out how to implement authentication/authorization with React and Node, using httpOnly cookies, with scalability optionality. I've read JWT can solve this by using refresh tokens and httpOnly cookies.
The number one problem for me is how to make it work the right way with react, because the httOnly cookie isn't accessible via JS.
The second thing is, I want my frontend and backend to live in separated, dockerized containers, but as far as I got it, the httpOnly cookies are added to the headers only for the same domain(and same port).*Update Actually, I've just read this is not true and I can use httpOnly cookie on same host, but different ports.*Update2, I've remembered what it was about: the "SameSite" property on the cookie. This will bind the cookie to the same origin, meaning port difference will consider as different origin and the cookie will not be transferred.
Can you please clarify this and maybe explain, does it really so important, I mean am I really will be in danger if I want to use some super-ultra-highly-secure website and yet, will use JWT with local storage(but with refresh tokens)? Does the httpOnly(and sameSite: true) cookies really will make a difference here?
Thanks
In my project (which is also Node + React) I did the following:
For each authenticated user (username + password) I signed two tokens, an access token and a refresh token.
I set the refresh token in the response header using httpOnly attribute. beware that latest versions of browsers won't allow third party cookies (from different domains) unless you set the attributes Secure and SameSite.
I return the access token as my response's body
Now in the client side (your React app):
You will get the access token in the response body, and here you have two options. To store it in local storage, or in memory. I chose to keep the token in memory instead because of a XSS vulnerability. (This obviously requires you to get another access token on each page refresh since the memory is cleared)
The refresh token is not accessible through JS you are right, but you don't need it. This token will be sent on each request, and usually it's expiration date should be a long one (I set it to 6-12 months)
Every time you want to gain a new access token (because it's expiration time should be
a small one, about 15-20 minutes), you will send a request to the server to "refresh" your access token, and the server will just check if the refresh token exists in the request headers, if not return a status of Unauthorized
EDIT: jwt tokens are not "secure" or "not secure", they are just tokens containing some data, and they allow you to make your authentication processs stateless (instead of managing sessions in your server). As long as you don't store any sensitive data in them, and sign them with a secret key that only you possess, you should be fine
EDIT 2: Since you are using react which "sanitizes" the DOM, a possibility of XSS is a minor one, so using local storage is ok and lots of websites do it. But because there is still a possibility (of you or a client injecting a script to some input element), I decided to store the access token in memory, which is a bit of a overhead but I prefer that.

Is JWT authentication is secure?how it protect CORS?

i have implemented the tokken based authentication in my project instead of the cookie-session based authentication. So, in jwt(jason-web-tokkens), every time is send req to server,I in headers attach the tokken and send it to server which validate it against the secret is used in generation the tokkkne in the first time and send me the response. Now, i have concern about it, first the tokken is saved in the local storage in browser.although the tokken is hashed but what if the hacker just take that tokken from storage and use it?
can anyone tell me how it stop the CORS attack?
I'm confused and cannot find any reliable answer online.
By CORS I think you are referring to XSS attacks? If so, the best way to prevent XSS is to secure your app against untrusted input. That is easier said than done, here is some information on that:
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
The easier way to prevent XSS is to store the token in a Secure, HTTP only cookie. This means that the Javascript environment cannot touch it, and it will only be sent over secure channels.
Nothing comes for free though :) If you put the token in a cookie, you will also need to setup a CSRF prevention strategy:
https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet
This can be a lot to take in!
I work at Stormpath and I recently wrote this blog post that covers these topics: Token Based Authentication for Single Page Apps (SPAs)

GWT Sessions and XSRF - the optimal solution?

Ok, first I was a bit confused when reading
Remember - you must never rely on the sessionID sent to your server in
the cookie header ; look only at the sessionID that your GWT app sends
explicitly in the payload of messages to your server.
at https://code.google.com/p/google-web-toolkit-incubator/wiki/LoginSecurityFAQ because I didn't understand the nature of XSRF completely and thought: why does it matter how the id gets transmitted?
Then I read http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html and now I understand that XSRF works despite NOT knowing the cookie content (your browser just attaches it to the request, so you exploit your browser's knowledge of the cookie's content - although the browser does not tell 'YOU' or the attacker about the content. The cookie content itself remains uncompromised by that attack). So any proof of knowing the cookie's content validates that the request is not part of XSRF.
I don't like the solution as implemented by GWT (http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html) because it needs a separate call to the server. Please tell me if my ansatz is secure and if I understand the XSRF stuff correctly:
To prevent XSRF, I just copy the session ID contained within the cookie into some non-standard HTTP header field, ie. "X-MY-GWT-SESSION-ID: $sessionId", when doing RPC calls.
That way, I do not need to make any additional calls during app startup because session validation is already done during delivery of the gwt app by destroying the cookie if the session is not valid any more (see How can delete information from cookies?).
So here is the complete security implementation:
registration: client submits cleartext credentials via RPC call to the server, which in turn stores the password using a hash during registration in the server's database (How can I hash a password in Java?)
login: client sends cleartext pwd via https+RPC, check password on server, if ok: store and return (via https) random UUID. That UUID is the shared secret stored on server and client that is used to identify the authenticated user over possibly many browser sessions to avoid requiring the user to log in each time he visits the site.
server sets cookie expiry time to 0 if session is not valid any more so that the client clears the session id and the GWT app detects that it needs to re-authenticate.
on server side only accept session UUIDs sent through a special HTTP header field to prevent XSRF
handle invalidated sessions on client side (either no session cookie or RPC request produced auth failure)
to prevent re-authentication shortly after gwt app loading, the server side devlivery mechanism (ie. index.jsp) deletes the cookie some time before the timeout actually happens - delivering a page and asking for authentication a few seconds later is a bit dumb.
Example sources for the GWT part can be found there: https://stackoverflow.com/a/6319911/1050755. The solution bsaically uses GWT XSRF classes, but embeds the MD5-hashed session ID directly into the web page instead of getting the token via a separate RPC call. The client actually never calls any cookie-related code and the server has only embedded a request.getSession().getId() call into the jsp page.
Any comments, suggestions, critique? Do I miss something important?
Disclaimer: I'm not a security expert.
Actually, if you obtain your xsrf token by an RPC call, then you're subject to XSRF, as an attacker could possibly forge both requests (this is very unlikely though, because it would have to read the response of the first call, which is most of the time prohibited by the cross-origin nature of the request and/or the way it has to be executed).
So ideally you'll make your xsrf token available to the GWT app through any mean.
You'll generally want your session cookie to be unaccessible through scripts (HttpOnly flag), so you'll need to find another way of passing the value (e.g. write it in the HTML host page that's delivered to the browser –as a JS variable, or a special HTML attribute on a special HTML element–, and read it there with GWT, either through Dictionary, JSNI or the DOM).
Also, you'll probably want to use both the cookie and the request header to validate the request (they must match), or you might be vulnerable to session fixation attacks (would probably need an XSS vulnerability too to make it truly useful)

Why does ServiceStack authentication use cookies rather than a sessionId header?

I'm loving using ServiceStack, but one question has come up from a colleague that I cannot answer. The Authentication mechanism sets a ss-pid and an ss-id cookie, which is explained here: https://github.com/ServiceStack/ServiceStack/wiki/Sessions
When trying to access a restricted resource, these cookies need to be provided, otherwise you'll receive a 401 Not Authorized result.
My question is this. Why use a cookie rather than a custom HTTP header value that includes the sessionId or equivalent cookie values? Is it because the cookie inherently has its own mechanism to maintain expiration? What were the design decisions undelying the use of cookies over HTTP headers?
HTTP Cookies are inherently sticky and is the most appropriate way for maintaining sessions over HTTP. After the server instructs the client to add a Cookie, every subsequent request that the client makes back to the same server will also retain that cookie - this what enables the Client/Server session.

Resources