lpotthast / axum-keycloak-auth

Protect axum routes with a JWT emitted by Keycloak.
https://crates.io/crates/axum-keycloak-auth
Apache License 2.0
34 stars 13 forks source link

Get Access token JWT from Cookie if exists #20

Closed kingsleyh closed 5 months ago

kingsleyh commented 5 months ago

Hi,

I'm wondering about the best way to check for cookies and get the JWT from the cookie if exists otherwise look in the Authorization header if no cookies. (or vice versa whatever makes more sense)

I guess the cookie name should be configurable. It would not be hard to get the token from the cookie this way - it's just a question of where to put the implementation and if it should be an optional feature?

e.g. if the decoding part was extracted from the part that looks for the token in the header then this would make it cleaner to implement this.

any thoughts or opinions?

Tockra commented 5 months ago

I think you could change the crate to archive this, but I see no real benefit. Further the cookie part of a request would add some security issues to your application which you need to fix like xss.

In a lot of cases a cookie between a server and a client introduce something like a connection state which is handled between server and client. The cookies need to be set by the server and the client just stores them. But exactly this we want no to have in our keycloak solution. The client just gets information from the keycloak server and our backend is possible to validate this data. Our backend does not talk with the keycloak server (usualy). I see no benefit in adding a session state to our keycloak setup.

If you do not see a real benefit in moving the bearer token to cookie, I would not do that.

kingsleyh commented 5 months ago

In my case I have a front end React app and the flow I have is this:

Why am I setting cookies instead of using a bearer auth token? The primary reason is for security:

For cookies:

So in summary for better security the access_token / refresh token should be stored in a cookie and not a local storage.

Tockra commented 5 months ago

Okay, from my perspective, it is peculiar to have a front end, a Rust backend, a Keycloak server, AND an auth server. I've observed similar setups, such as next-auth. However, I've concluded that this structure does not suit my application's architecture. Why should I maintain two different backends—one in Next.js and one in Rust? I see no advantage in doing so.

Some argue that storing the access token (JWT token) in the front end is insecure, so they keep it in their Next.js backend and access it via a cookie. But this means you always need to call your Next.js backend, which then enriches your request to your Rust backend with your access token. The response must travel back through your Next.js backend before reaching your front end. This adds complexity to your system. There's an additional hop in your network connection, and scaling your Rust application becomes less straightforward when system load is high. The most significant deal-breaker is that an attacker with access to your browser or hardware can steal your cookie with similar effort. So, why would I opt for this application structure? What's the benefit?

local storage is insecure and an XSS attack can steal the access_token (javascript can read the content)

I'm sorry, but this argument doesn't hold because cookies are similarly insecure due to the same or similar reasons. For instance, consider CSRF attacks: Exploiting XSS-stealing cookies, CSRF.

local storage has no built in encryption This doesn't protect anyone from theft with access to your device, as the decryption key is also stored on the device. Simply navigate to F12 settings -> Application -> Cookies, and you can inspect all your local cookies...

All websites SHOULD use HTTPS encryption, so there's no issue if your JWT token is placed in the header in plain text because the header is encrypted by HTTPS as well. And if somebody cracks your https connection then your JWT token should be already invalid (5-15 minutes validity of one token).

kingsleyh commented 5 months ago

Thanks for your comments. I'm not using a Next.js backend but my auth server would be pretty much the same in concept.

Putting aside the fact I've chosen to have an additional server to manage the auth process rather than communicating directly between React and my Axum backend. I have various reasons to do this which suit the architecture better due to supporting several web apps, mobile apps and federated SAML and other federated IDPs.

My preference is to use cookies over putting the token in local storage. Obviously there are pros and cons to where a token is stored but my view is that for auth in my case it's better in a cookie.

I guess you are of the view that this is not a good use case to make changes to this repo to support retrieving the token from the cookie. Which is fine. I will make a fork and put my changes there for my personal use.

Tockra commented 5 months ago

I guess you are of the view that this is not a good use case to make changes to this repo to support retrieving the token from the cookie. Which is fine. I will make a fork and put my changes there for my personal use.

I've nothing to decide here. If you build this feature in and it does not break the Authorization Header implementation I see no big reason why not to merge it. But back to the beginning, I've nothing to decide here.