How to secure private routes in SPA while using httpOnly cookies - authentication

I'd like to secure my SPA private routes with JWT authentication. To make everything as much secure as it's possible, I wanted to use httpOnly cookie to store my access_token on the client-side.
Using httpOnly cookies protect me a lot from XSS attacks, but unfortunately this approach does not allow me to check if the cookie actually exists in the browser.
In this case - how can I implement some logic to prevent unlogged users to visit private, secure routes of my SPA?
Am I forced to use non-httpOnly cookies or localStorage for this?

Am I forced to use non-httpOnly cookies or localStorage for this?
No. Keep your access_token in a cookie with the httpOnly flag, and (if possible) with the secure flag.
Let's call this cookie session_cookie.
When a user does a successful login you could return 2 cookies: the session_cookie and another one which informs to JS the user has been authenticated (let's call as SPA cookie).
Your session_cookie is not accessible by JS so it's not vulnerable to XSS. This cookie is sent on each request to the server, which checks is a valid token, otherwise an unauthorized error is returned.
Your SPA cookie hasn't httpOnly flag so it's accessible by JS but the server doesn't use it to authenticate the user, so fake this cookie is useless.
Whenever you receive an unauthorized error on your SPA you can remove the SPA cookie.

Related

Is it safe to store jwt access token in httpOnly cookie?

I watched a guide where an author stored access token in localStorage and then he put the access token as Authorization header with value "Bearer accessToken" in every request through axios interceptor. But I am wondering why not to store access token in httpOnly cookie as we do it with refresh token. What would be the problem if any?
It's safer to store access tokens in HTTP-only, secure, same-site cookies (it doesn't matter if it's a JWT access token). It's safer because the value of the access token can't be stolen through a cross-site scripting (XSS) attack. However, when you keep the access token in a cookie, you won't be able to send it to an API in an Authorization header. The browser doesn't have a way of setting the authorization header, it only attaches the cookies. That means that you might need a piece of software that will sit between your front end and API, and extract the access token from the cookie (this can be done e.g., by an API gateway).
Remember also that storing access tokens in cookies leaves you open to cross-site request forgery attacks (CSRF), but there are well-established techniques to protect yourself from CSRF. It is also simpler to protect against CSRF than against XSS.

How to handle refresh tokens in HttpOnly cookies with Hot Chocolate (GraphQL)?

I have an Asp.Net Core 6 GraphQL API app. Server setup with Hot Chocolate and endpoints are served at localhost/graphql.
When a user logs in GraphQL resolver generates both - access and refresh tokens, and sends in response as HttpOnly cookies.
An access token cookie has a path - "/", and a refresh token cookie has a path - "/graphql/refreshtoken".
The idea is that the browser in every request should send an access token, but a refresh token must be sent only when a client hits "/graphql/refreshtoken" endpoint.
I could not find any example with my scenario. And those that I found store refresh tokens in local storage, but not the cookie.
How can I setup the GraphQL server to serve /graphql/refreshtoken endpoint?
Note: I don't want to additionally use REST for refresh tokens.
If the above approach is not achievable, how can I refresh cookie-stored tokens with GraphQL? What is the best practice?

Remove httponly from cookie when making HTTP call using Flutter

I have an Express application that has a cookie-based authenticated route. I am using cookie-session to store auth tokens in the cookie.
I am developing a mobile app using Flutter and am using the requests package to manage cookies while making HTTP calls. I am able to make basic HTTP GET and POST calls.
My Express application has two routes - Sign In and Get Info. The route to Sign In authenticates the user and sets an auth token in the cookie using cookie-session. The Get Info gets information for an authenticated user, and the authentication is checked by a middleware.
The Express application is working as expected when I make calls using Postman or curl but is failing when I make calls using Flutter.
When I analysed the differences, I found that the Flutter application is adding an 'httponly' in the cookie, and consequently, the auth tokens are not being extracted. When making the same call using curl, it failed with httponly and worked when I removed the httponly flag in the cookie.
I tried toggling httponly in cookie-session by using sessionOptions and it has not worked.
Can someone help me out on this? I would be happy to provide additional information if it is required.

Where can I store my JWT token in client side?

We have some options such as localStorage, cookies, in-browser memory to store our JWT, I am also aware that localStorage is vulnerable to XSS, and httpOnly cookies are vulnerable to CSRF and it will be lost on reload/refresh when JWT is placed in the browser.
I studied about the latter issue and come to the solution that putting Refresh Token in httpOnly cookie and access token in browser memory can save me to some degree.
But according to my use case, I have an Admin dashboard from which only authenticated person(basically admin) can make authorised API call. Also, in my WebApp we don't have user input field(text field), So I guess XSS and CSRF hard to attack. So, Can I put JWT Token in httpOnly cookie with expiry of long duration?
Is this a good solution for my use case?

JWT authentication using cookies with KONG API Gateway

We are implementing a sample application using Kong API gateway with JWT authentication plugin.
As refer in this thread, there are two ways to store JWT in the browser. Web storage or cookies. But web storage (i.e. session storage and local storage) can be vulnerable to cross-site scripting attack(XSS). So other option is cookie. (Though CSRF should be taken care off)
I have two questions,
If we use web storage to store JWT then is there any way to stop XSS. If yes then how it will work if the same page is open in the new tab or reload the same page ?
Using cookie: We are able to send the cookies in the request. But KONG is authenticating the end point URL only if the JWT is set on headers (Authorisation: Bearer token) and not authenticating using cookies. Is there any way to verify JWT which is set in cookies using KONG API Gateway ?
There is nothing wrong about storing JWT in webStorage, unless you store sensitive data in your JWT (but you should never ever do that, since you can decode it easily). The point is that your token shares a secret, that only your servers knows (that's what makes it secure), you should just put an expiration time to make it a lot safer.
And no, you cannot pass a JWT token in cookies, it's only in headers (here Authorization), I don't know about KONG API, but they should not allow that !
(ref about JWT is here)
In order to add to #antoine2vey answer,
It looks like your on page application is being served from a protected API in Kong at the "/" (slash) resource. I would suggest that you would be able to get the page content from an unprotected "/" (slash) resource and then run javascript code would have access to the cookie and would be able to perform the request to the protected resource passing the JWT token in the header where Kong would be able to validate for you.
Does this make sense?
Cookie based authentication is implemented. https://github.com/Kong/kong/pull/2973