React & Express JWT Auth: Is it safe enough to store access tokens in Cookies? - reactjs

I've spent a few days trying to figure out a secure authentication method for SPA/React (client-side).
Most of the tutorials I've read in the wild contradict each other.
One says have to store in Cookies another in Local Storage, one says don't need to use refresh token, one says have to use a refresh token.
I'm building a React SPA app for the frontend and Express for the API (backend). Both are stored in the same domain:
React: example.com
Express: api.example.com or example.com/api
Is it enough to secure my application by using Cookie (access token JWT):
httpOnly:✅
secure: ✅
sameSite: strict
without refresh token
This matches the answer here: https://stackoverflow.com/a/57779076/11340631
The question is:
Is this safe enough?
How long does it take to set the expiration of the access token?
Is this as per Oauth recommendation?: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps
What if my access token is stolen? For example, my friend is using my PC and he stole my cookies and use it in his PC browser.
I really hope to get the answer here, any answer is appreciated.

It's safe against extracting the token with Cross Site-Scripting, but, without other security controls it might be prone to Cross Site Request Forgery (cookies are automatically attached to a request). Is API accepting key in the cookie or must it be sent in the Authorization Bearer header?
My concern is, that if you're not using refresh token, the access token must have a relative long expiration. OAuth2 was not intended to be used to authentication alone, but together with some session-like solution, for example OpenID Connect and SSO.
The shorter the better, unless it can be revoked any time server-side. If there's no way to revoke the key, the 5 minutes expiration date is, in my opinion maximum. That's why refresh token and session-like endpoint is the must.
OAuth is not designed for web application client's authentication at all. That's the common anti-pattern in many projects I've pentested. https://oauth.net/articles/authentication/
I'm glad for your awareness of such a threat. Access tokens must either live very shortly, or they must be revoked server-side in a some way, for example by utilizing some kind of revoke-list. Or the refresh token with server-side-like session endpoint should be utilized.

Related

Refresh token in Desktop App for OAuth2 Authorization Code Flow

I want to use API in my .net WinForms application which are closed by JWT token. Such tokens can be received from the Identity Provider using Authorization Code Flow + PKCE. I worked with such flow before in Web Application and I know how to request code, exchange it on the access token and I used silent refresh approach to refresh the access tokens.
For my clientId I'm not able to use refresh tokens. So, I'm slightly confused how to implement to refresh tokens in the Winforms application.
It's definitely I need to open Login page to allow the customer enter credentials. Then I guess I need to catch code from the Redirect URL. It seems I need to use loopback IP address as a redirect URL and catch request in the application.
But how to set up refreshing process I have no idea. Please help with advice or add links to examples.
For a desktop app you should follow the recommendations from RFC8252. Without a token refresh you will get usability problems. Eg access token expires after 15 or 30 minutes, then user experiences a re-opening of the system browser.
This might be fine for a high security app, such as for banking, but for most apps it is not what you want. Alternatives such as long lived access tokens are bad from a security viewpoint, since the long lived value is then exposed on every API request.
You won't be able to use silent renew via hidden iframes either, since you don't have that much control over the system browser. You can only open it by executing a URL.
So you have these main choices, and maybe you can explain trade offs to stakeholders. You won't be able to implement a workaround in code:
No refresh token, and sub-optimal usability
Refresh token used, so a longer lived API credential is used in a public client
Locking down what can be done with an access token issued to the desktop app - using scopes and claims - is usually the main mitigation of this type of security concern.

Using React with KeyCloak - Do you actually need to store the JWT?

I've been learning about how to use Keycloak from React (with the Keycloak javascript adapter) with the scenario that Keycloak will provide SSO, allowing the React application to authenticate users with Keycloak, and then use the access JWT provided by Keycloak for bearer authorization with some secured REST api.
I have read lots of discussion on Stack Overflow about where is the best place within React to store the JWTs that Keycloak provides when the user is first authenticated (i.e. context / redux / local storage / cookies). However whatever choice you make about storing a JWT there is always a risk of a XSS attack and the token therefore being obtained by someone else. Because you'll be storing a refresh token as well as the access token, if these are both at risk of being compromised then that would be less than ideal!
Thinking about this I'm wondering if it's actually possible to not ever need to store these tokens in memory at all. I am wondering if the following scenario woud work, and if so (1) is it a better security approach or have I missed something, and (2) are there any disadvantages to it?
The plan is this... When the user first runs our React application we authenticate the user via Keycloak, which might require a login / authentication process. React gets the response back and only extracts and stores from the response the parts that the React application needs to operate, such as some user information and resource roles. But we won't store the JWTs, instead we will instantly discard them.
When the React application subsequently needs to make a rest call it first will re-authenticate the user via keycloak, which will be a seamless / non-visible process from the user's point of view, as they are still authenticated as far as Keycloak is concerned. (On that last point I'm guessing that this is done by a session cookie from Keycloak?). Keycloak will respond to the react application with the tokens, we extract the access token and use it to make the required rest call, and then the React application can discard the token immediately after it has been sent to the server.
Have I come up with a genius idea, or is this seriously flawed???

Token based authentication in spa (React)

As I realized refresh token not supported in spa (react) .
Because it can not protect it .
So series of questions came up to me :
1 - Can we use long time access token in spa ? Is it secure?
2 - Is alternative solution for refresh token?
3 - Should we use the 3rd party identity server such as identityserver 4 or we can implement token generation Ourselves). What is best practice?
A bit late, but still...
You are right in terms of that refresh token should not be returned by Implicit Grant which is used to authenticate users in SPA applications. And yes, the limitation is due to a browser is unable to keep it private.
1 - Can we use long time access token in spa ? Is it secure?
We can, but whether it will be secure would depend on your application's security policy.
To keep it short, here is an example of how you can consider Access Token Lifetime to be specified for various security requirements.
2 - Is alternative solution for refresh token?
Yes, it is called Silent Authentication and briefly it looks like this:
a client (SPA app) obtains an Access Token and expires_in parameter
Identity Server provides an auth session (cookie) so the app can request a new token without providing credentials since it's already authenticated at Identity Server
in case of session's sliding expiration a client pings Identity Server to keep the session alive as long as needed
once the Acces Token becomes expired and auth session is alive (a check might be needed), a client requests for another Access Token (this is usually done in a setTimeout), but in this case providing a parameter to tell an Identity Server that consent screen should be dropped (usually it is prompt=none)
Resources:
Azure AD Silent authentication
Auth0 Silent authentication
3 - Should we use the 3rd party identity server such as identityserver 4 or we can implement token generation Ourselves). What is best
practice?
That would depend on the size of your application and whether you need just a token generation or something more (like Federated authentication out-of-the-box, various grant types, etc.).
For big enterprises (if there's no need to reinvent the wheel) it is always the best practice to use a production-ready 3rd party library (Identity Server 4 or OpenIddict) unless you have a small application (MVP, prototype, etc.).
Identity Server 4 needs some effort to configure it the right way and may simply be excessive. OpenIddict is a bit easier alternative.
Custom token generation is something that we used to do before Identity Server emerged. Today it is only a matter of having a quick solution for your custom authentication needs.
Worth to mention this project JWTSimpleServer for simple JWT authentication.

JWT + OAuth2 + ADFS 3.0 + Mobile + API

I’m building a mobile app and API secured with JWT tokens issued from ADFS 3.0. The mobile app is registered as an OAuth2 client with ADFS. I’m concerned someone could intercept the JWT token and use it to access the API maliciously.
My question is will this be enough to secure the API?
the token is indeed sensitive but this is mitigated by a few factors.
The token is passed in the Authentication Header. This is why you need to only pass it via an https call because the header gets encrypted at that point and is secure.
The token is only valid for a while .... and you can set this value to whatever you want. I had them setup for 1 hour for example. Even if someone does get a token, they can only use it for that time after which it becomes invalid.
You will need to secure the method of generating the token as well. Keep the ClientID and ClientSecret safe. Don't pass them in a URL for example as that can get intercepted.
If you do all this you will be as safe as anyone can be on the internet.
One final point from me, some people like to store the tokens in a database. I would recommend against it. Keep them around in your client app, yes, in a secure way so you can reuse them until they expire, but don't use any traditional storage which can be stolen, hacked etc.

CSRF in token based authentication

We have a token based OAuth authentication mechanism for our angularjs application. The acunetix tool indicated that XSRF threat is there.
Is CSRF an issue for token based authentication (Because we are not using any cookies for user identification / authentication / sessions)?
If CSRF is an issue for token based authentication, is there be any way to implement prevention without using cookies?
As far as I know token based authentication is in no way affected by CSRF. E.g. if you use cookies, and bad guys lure users into their site where they can create a special button that will do a post to your site -> here is CSRF where you can execute some requests on behalf of the users.
Now if you use tokens that are stored in session/local storage e.g., they are never automatically passed with the request. You probably use something like angular interceptor or similar technology to pass it along with every XHR request. This never happens automatically.
You can read a bit more on token auth in this very good post. In point number 6 there is a little section about XSRF/CSRF, XSS.
In my modest experience these big security tools can often tell you something that is not true just to make themselves more "significant". But it would be interesting to know exactly how it plans to execute CSRF and what exactly made it think it is possible? E.g. you might have a cookie that you missed?
P.S.
XSS attack (to steal token) gets more possible with tokens, since you can put HTTP-only like for cookies. So any successful XSS will be able to read your token, so you need to make sure that you have a good protection against that. But it's usually covered well by frameworks.

Resources