[HN Gopher] Authentication with Axum
       ___________________________________________________________________
        
       Authentication with Axum
        
       Author : mattrighetti
       Score  : 76 points
       Date   : 2025-06-04 23:33 UTC (23 hours ago)
        
 (HTM) web link (mattrighetti.com)
 (TXT) w3m dump (mattrighetti.com)
        
       | mrbluecoat wrote:
       | Not sure how this is better or easier than Neon Auth mentioned a
       | few articles further down on today's HN homepage:
       | https://news.ycombinator.com/item?id=44184849
        
       | ripley12 wrote:
       | This is very useful, thanks. I've implemented similar
       | authentication with tower_cookies in a home project, and it took
       | me a _long_ time to figure out; Axum is powerful but not always
       | the most intuitive. It was a great learning experience, but I 'd
       | love to offload more of this to a crate next time.
        
         | tonyhart7 wrote:
         | I think https://loco.rs/ is better choice for you then
        
           | echelon wrote:
           | Rust ORMs still don't feel great. They're verbose, the
           | tooling is flaky, and they feel fly-by-night. They're
           | surprisingly not very type safe either. I'd rather use Rust's
           | sqlx until the Rust ORM situation improves.
           | 
           | Axum and Actix are already drop in replacements for something
           | like Flask. They're mature and good at what they do.
           | 
           | The dream of a Rails or Django in Rust is still really far
           | off. I'm glad the Loco folks are trying, but it needs a lot
           | more magic and maturity to truly bear that comparison.
        
             | tonyhart7 wrote:
             | wdym magic, its rust
             | 
             | there is no magic only a lot of macros, and someone must
             | write them
             | 
             | if you talking about mature, of course 20+ years web
             | framework is more mature + have more feature than loco.
             | what kinda comparison is that
        
             | Spartan-S63 wrote:
             | Back when SeaORM first released, I was excited about
             | another ORM that supported async (as Diesel didn't have an
             | async shim at the time), but man does it have some _weird_
             | design decisions.
             | 
             | The underlying query builder's API is just downright odd.
             | The ActiveRecord pattern is fine for SeaORM, but it's
             | just... weird. The ergonomics aren't right.
             | 
             | It's sent me down the path of wanting to design an ORM for
             | myself that has the ergonomics I want. Nothing really to
             | show yet at this point, but still something I want to build
             | out someday.
        
               | Jalad wrote:
               | Can you please explain what you found weird? I just
               | started using sea-query and haven't found anything super
               | odd quite yet, but I've only written a few migrations and
               | queries so far
        
               | mattrighetti wrote:
               | I can say a word or two about sea-query.
               | 
               | I've used it for 3-4 months in a lot of my projects. For
               | very basic queries it worked very well and I liked it
               | quite a bit, but as soon as I had to do something a
               | little less standard that's where I started to see the
               | issues.
               | 
               | Documentation is not really there yet and I ended up
               | loosing tons of time trying to look for the right
               | function in the crate that would translate in the query I
               | had to make. I've blogged about that too if you're
               | interested [0] (TLDR: I got back to using raw SQL)
               | 
               | [0]: https://mattrighetti.com/2025/01/14/ditching-sea-
               | query
        
             | jtwaleson wrote:
             | I'm using Loco a lot since half a year, and have
             | contributed some upstream patches. It's definitely not
             | Rails, but where I was always afraid of refactoring Python
             | applications, that fear is pretty much gone with Loco/Rust.
             | That, and the incredible performance make me enjoy it a lot
             | now. You pay extra with development time, but you get it
             | back with long term maintainability.
             | 
             | My main remaining gripe is the Rust compilation speed...
        
             | dgroshev wrote:
             | I don't think "glue" frameworks like Loco can get us there
             | tbh. One problem is that frameworks like Django or RoR
             | _have_ to be tightly integrated! Auth needs to be aware of
             | models and sessions, autogenerated admin pages like Django
             | have to rely on model metadata, templates and view code
             | might need to be aware of cache busting and static file
             | handling, etc etc. It 's a tough problem and a very high
             | barrier to creating a new comprehensive framework.
        
           | Scarblac wrote:
           | I looked into it recently. Apparently it has session based
           | auth.
           | 
           | I tried to figure out how to do the first thing that came to
           | mind: on an incoming request, check that the user is
           | authenticated, and if not redirect them to a login page with
           | a ?next= parameter to be redirected back to after login.
           | 
           | Couldn't find a way to do it. In Django you use the
           | @login_required decorator on a view and that's it.
        
       | johnduhart wrote:
       | > I won't get sucked into the session ID vs. JWT argument, but
       | honestly, using JWTs in cookies is a win because you don't have
       | to fuss with storing session data on the server.
       | 
       | Okay, but then you implement storage of the refresh token and
       | build this bespoke JWT re-issuance logic. So where's the win
       | here? Just use sessions.
        
         | maz1b wrote:
         | What's wrong with storing JWTs in httponly cookies? Having a
         | way to validate and track JWTs is a valid use case.
        
           | unscaled wrote:
           | 1. Cookies remain valid on logout (unless you implement a
           | session revocation mechanism). This can be mitigated by
           | making the JWT live a very short time (e.g. 5 minutes), but
           | you still don't get immediate expiry. This may not be
           | acceptable if you need to comply with certain standards such
           | as PCI/DSS, SOX or HIPAA.
           | 
           | 2. Cookie size could grow much larger. It's generally not a
           | huge concern if you don't stuff too much data into your JWT
           | claims, but if you want to optimize traffic for slow
           | networks, JWT is not a great choice.
           | 
           | 3. Since 50% of the JWT standard (and 90% of the JWE
           | standard) is made of broken and semi-broken algorithms, you
           | need to be careful on what keys and libraries you use.
           | Unfortunately, we cannot see the implementation for this
           | article, so we cannot judge how safe it is, but JWT just
           | requires extra care compared to Session IDs.
           | 
           | 4. If you're using refresh tokens because your JWT is short
           | lived, you're not really saving yourself any work, because
           | you'd still need a database to store the refresh tokens. This
           | is what GP was referring too.
           | 
           | > using JWTs in cookies is a win because you don't have to
           | fuss with storing session data on the server.
           | 
           | This is the author's claim, but the code clearly DOES store
           | data on the server, for the refresh token.
           | 
           | Using JWT for "simplicity" is unfortunately common mistake.
           | With JWT you can choose between simple (no storage required,
           | no token revocation) and secure (immediate or delayed session
           | revocation at the price of requiring storage). You cannot
           | have both. OP chose security (by using a refresh token
           | database), but this is no longer a simple solution. If you've
           | already deployed a DB, Session IDs would always be simpler:
           | 
           | 1. You could remove the refresh and redirect logic entirely.
           | 
           | 2. You would only need one type of cookie.
           | 
           | 3. You can remove dependency on JWT libraries, choosing the
           | right cryptographic algorithm and configuring (and securing!)
           | JWT signing keys.
           | 
           | This comes at no cost, since the refresh token DB is already
           | there.
           | 
           | There can be good reasons to use JWT (although there are
           | better standards out there for stateless tokens[1]), but
           | simplicity is not one of them. Stateless tokens can be useful
           | in the following cases:
           | 
           | 1. Performance (increasing throughput or reducing latency by
           | skipping the database for most calls).
           | 
           | 2. Reliable cross-regional tokens (you don't need to
           | replicate session IDs across regions and suffer from
           | inconsistencies during failovers).
           | 
           | 3. Decentralized verification (without relying on a central
           | database).
           | 
           | 4. Offline attenuation without network calls (with Macaroons
           | or Biscuits only).
           | 
           | Unfortunately it seems like in 99% of the cases JWT is chosen
           | as the access token format, it's chosen by its perceived
           | simplicity and popularity, and the result is either a toy
           | implementation that doesn't support token revocation, or an
           | implementation that is more complex than it would have been
           | with classic Session IDs.
           | 
           | [1] https://fly.io/docs/security/tokens/
        
             | mattrighetti wrote:
             | I agree with the overall JWT statements you made.
             | 
             | > This is the author's claim, but the code clearly DOES
             | store data on the server, for the refresh token.
             | 
             | You're right, but I was making a different point about
             | session IDs versus JWTs.
             | 
             | With session ids, each user request requires a server-side
             | lookup to validate the session. For that reason, their
             | ideal place would be something in-memory and that's what I
             | was referring to with "data on the server".
             | 
             | While storing session IDs in a database is an option, in my
             | case it would introduce noticeable latency because I self-
             | host my projects on a cluster of Pis at home and even
             | though I have a fast connection, a roundtrip to my external
             | (I don't self-host it) database still takes a few
             | milliseconds under low load.
             | 
             | JWTs allow me to avoid frequent server-side lookups. I can
             | trust the client's data without hitting the database,
             | except when issuing a new JWT - but even then, that happens
             | every 2-3 minutes per user. While verifying JWT signatures
             | and decoding claims does consume some CPU cycles, this
             | overhead is minimal on my setup compared to the latency of
             | database roundtrips.
             | 
             | Nothing against session ids, but I feel JWTs are better
             | suited for my resource constrained setup.
        
         | VWWHFSfQ wrote:
         | The major benefit of this approach is that you can avoid a
         | database lookup when you have a valid JWT available. Only in
         | cases where it's missing or expired would you need to hit the
         | database for a refresh token.
         | 
         | This might not matter for trivial apps, but for very high-
         | concurrency web apps this will matter a lot.
        
           | 0x457 wrote:
           | Sure, but unless you're near Google scale, you probably
           | shouldn't worry about that. IMO JWTs should not be used on
           | public internet.
        
       | Goofy_Coyote wrote:
       | > HttpOnly Attribute: Prevents client-side JavaScript from
       | accessing the cookie, neutralizing XSS attacks
       | 
       | Just a note that 'HttpOnly' doesn't neutralize XSS.(although this
       | is not the main point of this blog)
       | 
       | This is dangerously misleading. HttpOnly prevents cookie theft,
       | but it absolutely doesn't "neutralize" XSS.
       | 
       | First, even with HttpOnly cookies, malicious JS can still make
       | requests on behalf of the user - the browser happily attaches all
       | cookies (including HttpOnly ones) to XHR/fetch requests. So an
       | attacker can still
       | 
       | `fetch('/api/admin/add-user', {method: 'POST', body:
       | JSON.stringify({email: 'attacker@evil.com', role: 'admin'})})`
       | 
       | or delete data, transfer funds, whatever the victim is authorized
       | to do. They don't need to read the cookie, they just need the
       | browser to send it.
       | 
       | This is why many apps ask for your password to change your email
       | or reauthenticate you/trigger an MFA workflow when doing certain
       | things.
       | 
       | Second, tons of XSS attacks don't even care about your cookies.
       | They can rewrite the DOM with a fake login page and harvest
       | credentials directly. They can keylog everything you type. They
       | can steal data that's already on the page, redirect you to
       | phishing sites, or mine crypto with your CPU.
       | 
       | HttpOnly is a good defense-in-depth measure, but calling it a
       | neutralizer for XSS is like saying a seatbelt neutralizes car
       | accidents. You still need proper input validation, (contextual)
       | output encoding, CSP etc.
        
         | mattrighetti wrote:
         | You're right, I poorly worded that sentence. I was specifically
         | referring to XSS attacks targeting cookies or data like
         | localStorage/sessionStorage.
        
         | imtringued wrote:
         | I fully agree. Anyone who wants to defend against XSS should
         | have a tightly locked down CSP. That's the only way. (no,
         | "careful" coding isn't reliable enough)
        
           | varun_ch wrote:
           | I think you mean a tightly locked down CSP _and_ "careful"
           | coding (just escape practically everything you render), a
           | tightly locked down CSP is also not reliable enough.
        
         | hiddenfinance wrote:
         | with GPU finger printing cookies are least of my concern now
         | days. Cookies are about as good as a web session it should be
         | discardable if needed.
         | 
         | Yeah but once the attacker get access to the JS they can do
         | whatever. That is why stop using CDN for your jquery or react
         | libs!
        
           | diggan wrote:
           | > That is why stop using CDN for your jquery or react libs!
           | 
           | I agree, but for adding a bit of security to those who
           | must/want to use CDNs regardless, make sure to use
           | Subresource Integrity https://developer.mozilla.org/en-
           | US/docs/Web/Security/Subres...
        
         | julienfr112 wrote:
         | Absolutely, there is a confusion with same-site=strict, witch
         | effecively prevent XSS.
        
       | 0x457 wrote:
       | I think storing JWT in cookie is madness. You got every downside
       | of JWT without any upside at all.
       | 
       | Use a normal session, since you already assume there is a db for
       | authentication.
       | 
       | That JWT token takes much more space on a client (and sent with
       | every request!) than a proper session cookie would.
       | 
       | That JWT refresh token would also take more space than what you
       | store in claims would take up even if you naively stored it in DB
       | (i.e. not via relation between user and session).
       | 
       | IMO, the only way to correctly use JWT for authz (authn is
       | handeled somewhere else as it should):
       | 
       | - authenticate user somehow (not JWT probably, unless it's a
       | federated login)
       | 
       | - issue a short-lived JWT with required claims
       | 
       | - pass that JWT with requests to other backends
       | 
       | - now backends can validate that JWT by themselves
        
       | skwee357 wrote:
       | In the ancient times before SPA era, we used to generate sessions
       | in the server and return them in the cookie. Upon every request
       | you would check the cookie value against the db table and if a
       | match found, you have an authenticated user.
       | 
       | But then came an era of SPA and we needed another way to
       | authenticate users, since XHR did not (and still not?) supported
       | cookies, so we created the signed JWT token.
       | 
       | I'm a bit confused as to why one would want to store JWT access
       | and refresh token in a cookie? Axum provided both signed (temper
       | proof but not secret) and private (allows you to save sensitive
       | information) cookies. Why wouldn't you use these instead of
       | saving JWT in cookies?
        
       ___________________________________________________________________
       (page generated 2025-06-05 23:01 UTC)