Hacker News new | ask | show | jobs
by georgekb 1729 days ago
Thanks for this great post. I actually just signed up to say that I actually wasted a considerable amount of time trying to create my own SIGv4 just to avoid replay attacks especially if the server is behind some L-7 load balancer such as Cloudflare more than any other reason. It was implemented like this: the server creates a ecdsa/ed22519 key pair, hands over the private key to the user and keeps only the public key, then for every request to the actual APIs, the user uses the private key to create a JWT that contains some attributes such as the userID, sessionID, the request path, etc...). While this method obviously looked much more secure than just a long-term static JWT or an access token, the real problem I found was in the clock skew, if the client doesn't have a well synchronized clock, then the JWT is deemed invalid by the server since such this JWT should be very short-lived by design otherwise what's the point of having them in the first place. If your clients are browsers or running on PCs, as opposed to servers, containers, etc... this will be a huge problem for you. In fact, AWS clients implement their own clock skewing correction https://aws.amazon.com/blogs/developer/clock-skew-correction...

I ended up implementing an additional auth API endpoint where you use your long-lived secret to periodically request a short-lived JWT that is only valid for a few hours, this short-lived secret is what is used for the actual APIs to authenticate the users.

2 comments

Your first approach reminds me of http message signature:

https://datatracker.ietf.org/doc/draft-ietf-httpbis-message-...

Library support for it is spotty, depending on your framework of choice but they exists.

Your second approach is covered by oAuth refreshable tokens I believe.

I went through the same process as you in an API project, eventually ended up using Keycloak as the auth server.

Wow, never heard of HTTP Message Signatures until now. However, like I said, Clock skew is a huge problem in this method. I found out about it much later after implementation when I used the client on some old Windows machine whose clock wasn't synchronized and I spent like a day until I figured out it was the clock skew which made this whole method look suspicious to me even it's obviously much more secure. It could be great in a microservice environment where you're pretty sure that all your endpoints have well synced clock, but when your clients are browsers and PCs, it is about time until you experience it.

As for the second approach, yes exactly it's very similar to OAuth2. In fact I guess this is the method used by GCP APIs by service accounts. The clients use their long-lived secrets to get an oauth2 access token, this access token is JWT I guess that also contains authorization information such as scopes.

I was pretty sure that you can approximate this in aws iam just with policy conditions on “aws:CurrentTime”

But after much googling it appears not! Seems like a fairly simple additional variables aws could pass through and condition to support, so you can say “only allow this request if the signing time is < 1min ago”, closest you can get is that the policy is only valid after X date! Is a shame!