What's OAuth2, anyway?
romaglushko.com
romaglushko.com
This being hackernews, any comment worthwhile cannot be devoid of criticism. Trust-on-first-use is used incorrectly here -- saving the previous authorization scopes is just caching. TOFU has a specific definition in security: it's when you're establishing a secure channel but you haven't shared a secret or public key a-priori -- it makes it impossible to guarantee that the counter-party is whom they say they are. Very concretely TOFU is a diffie hellman key exchange with a shared secret that can be MitMed. Through use in time the shared secret gains integrity because the probability of a persistent MitM accross channels degrades. The most common place TOFU is encountered is when connecting via ssh to a server and the server accepts your connection because you're in their authorized_keys but the server's key is not in your known_hosts.
[0] https://www.oasis-open.org/standard/saml/ or https://saml.xml.org/saml-specifications
It's mess.
However after years I still don't understand the technical differences between OpenID Connect and OAuth2. Can a OAuth2 client connect to a OpenID Connect server?
OAuth2 technically only offers "authorization" (granting access to do something), but OpenID Connect adds an "authentication" (who is getting this access?) layer on top of OAuth2 by returning an id_token alongside the authorization_token.
The original OAuth 2 RFC is a very easy read and it's clearer than most specs out there. It's certainly far easier to read than any W3C spec.
I think the main issue is that there are too many specs that have been added over the years, and you need to know the right ones to implement. Some specs should be mandatory (like Bearer Token Usage, PKCE, OAuth for Native Apps and Current Best Practice[1] and Browser-based Apps[2] when they come out of draft). Some are useful only for certain use cases (Device Authorization Grant, Token Inspection Endpoint and Token Exchange). Some specs are horrible abominations that would hopefully never be implemented (I'm looking at you RFC 9101 JWT-Secured Authorization Request).
The good news is that OAuth 2.1 incorporates some of the best RFCs I've mentioned into the core RFC. This would help make OAuth simpler by having one document to point out to. I hope it comes out soon, since at this point I still have to fight with people who think that using the Password Grant is a great idea and have no idea why they should implement PKCE or CSRF protection.
OpenID Foundation seems took a path of making "profiles" like FAPI rather consolidation and enforcing the best practices and depricating the bad.
FAPI (Financial-grade API Security Profile 1.0) https://openid.net/specs/openid-financial-api-part-1-1_0.htm...
I hope the community will combine it all at some point and add specifications for proper policy and resources management too by looking at the full lifecycle of modern applications.
Knowing the OpenID foundation, this could be yet another undocumented errata set released, but we can still dream of a better world, can't we? In a better world, instead of "Use 2048 bit RSA keys" the spec will say "Don't use RSA ever."
The advanced FAPI has even more directly bad advice, as requiring PS256 and ES256. Now, these are not so bad as the common RS256 (RSA with PKCSv1.5 padding), but they are still bad algorithms. The only good asymmetric algorithm defined in JWS is EdDSA, which just like that, is forbidden by OIDC FAPI. So I'm quite happy FAPI is just a profile that would mostly be ignored.
At this point the main differences are:
1. PAR: A good idea that should become a part of the OAuth standard, even if it costs an extra RTT. It prevents a pretty large class of attacks.
2. "iss" response parameter becomes mandatory (it is a core part of OAuth 2.1, but considered optional). This is a useful measure against mix-up attacks in certain conditions, but the conditions that enable it are less common than the ones
3. Requires either Mutual TLS or DPoP. I am less sold on that.
Mutual TLS is great for high security contexts, since it prevents Man-in-the-Middle attacks and generally comes with guaranteed key rotation. But mTLS is still quite troublesome to implement. DPoP is easier, but of more questionable value. It doesn't fully protect against MitM, keys are rarely rotated and it is generally susceptible to replay attacks against you take costly measures and it relies on JWT being implemented securely, by a developer who understand how not to shoot themselves in the foot with their brand new JWT Mark II shotgun. The
4. Which bring us to cryptographic algorithm usage guidelines. These are not part of OAuth 2.1, since OAuth does not mandate or rely on any cryptography with the sole exception of the SHA-256 hash used for PKCE.
This is good design. When there is an alternative that doesn't require cryptography (such as stateful tokens or the authorization code flow), it is generally more secure. You have one less algorithm to worry about being broken (e.g. by advances in quantum computing).
For what it's worth, the guidelines okay, but not good enough. RSA is still allowed. Yes, it requires PSS and 2048 bit keys, but there are knobs left that you can can use to generate valid but insecure RSA keys (e.g. a weak exponent). With EdDSA there is no such option. Weak keys are impossible to generate. Considering EdDSA is also faster, has smaller signature size and better security, there are no good reason to use RSA (and to a lesser degree ECDSA) anymore.
In short, in an ideal world I think I would just want OAuth 2.1 to incorporate PAR and make the "iss" response parameter mandatory. The cryptographic (JOSE) parts of the specification seem to me like too much add complexity, for too little gain, with too little in the way of making cryptography safe.
As an application writer, I want the user to feed me a token signed by a trusted entity that proves he is who he claims he is and has the necessary accesses enabled for my application.
Whether this happens transparently via a redirect to the trusted entity login webpage and back to my app or whether I request the user to go to a specific url on their own while I wait for them to do so is just an UX detail. Why every approach needs to be labeled a "flow", authorized separately, and come with their own limitations is beyond me.
The reason they're called flows is because they each compose one or more single steps from the OAuth2 "toolbox" (i.e. endpoints). Many flows will have overlapping or even identical "steps", but the order of things matter and the modes in which they interact matter, which is why the second layer of delineation is necessary (or useful, at least).
good luck
The problem still existed, and other developers took a stab, but they weren't protocol or cryptography people, so we got a bunch of mostly broken stuff. Some cryptographers came along and pointed out the disasters, and since then it's been slowly getting better, but it's still a giant mess.
Companies have decided, since we have to solve it for us, we can just solve it for you too, and now we have "social logins" where we tell Microsoft, Apple or Google everything we login to. They appreciate the extra information to help themselves, so it's a worthwhile incentive for them.
The web browser developers got a little involved with passkeys, but the UX is still not idiot proof. Better than their last two tries at implementing public key auth though(TLS client certs and DOD auth).
Yes, indeed.
> I find everything related to this auth business needlessly complicated and arbitrarily limited.
You find a subject you do no understand or were bothered to learn about to be needlessly complicated and arbitrarily limited?
> Most of the time it's not even implemented correctly anyway (many application not checking the JWT audience...) because web devs (...)
You seem to be very opinionated over things you clearly know nothing about.
Among the many ways you manifested your cluelessness, OAuth is not a "web dev" thing. It's a "software communicating over a network" thing. Desktop apps must support it, so do mobile apps, and web services need to support it both as client apps and resource services.
Also, to drive home your clueless ignorance, "checking the JWT audience" is not a authentication thing, which is the responsibility of OAuth. The full name of OAuth2 is "OAuth 2.0 Authorization Framework". It covers delegating authorization to third parties so that clients can access a user's claims. Claims are not authorization either.
In the end you were awfully critical of something you don't even know what is?
> (...) just use libraries without understand what actually provides the security.
I think you should take a step back and meditate over your post. It says nothing about OAuth, and everything about how little understanding you have over OAuth and how vocal you are on a topic you know next to nothing.
JWT is by far the most important building block here, and while it's not part of OAuth, realistically it's how anyone sane would use OAuth.
There's a degree of confusion in your comment. I pointed out the fact that OAuth handles authentication, not authorization. Those who fail to understand this clearly don't know the basics of the whole system. This is what I posted in my previous reply to your post.
The same applies to JWTs. They are the output of an authentication process. They do not authorize anything. They bundle a set of claims along with metadata used to prove they can be trusted and when they are valid. They are designed in a way that resource servers can validate them locally before actually handling any authorization concern.
The authorization part is handled by the systems which check these claims. It's a separate concern, handled separately by separate systems. If you were familiar with any OAuth flow, you'd be aware that this part takes place only after any of the flows take place, and is way outside of their scope.
This is what I'm talking about. If you do not understand the problem domain then you are in no position to criticize or complain about how solutions are implemented. You can only complain about the time you're wasting criticizing things you know nothing about.
Restricting the scope is mostly useful for when you need to interact with services that talk to other underlying services without granting them full access to those, but in practice, that's not a very common case outside of the web.
Ultimately that distinction doesn't really matter, what's important at the end of the day is how you implement the access control. Using an opaque token and an introspection endpoint is a terrible idea. JWT is a good solution. All of the OAuth flows do is just provide convoluted ways for the user to authenticate with a identity provider, generating a JWT on his behalf, and do not contribute to security in any meaningful way.
It's always very jarring to come across a post that is so drastically different in tone when you're just trying to follow a comment thread.
> I think you should take a step back and meditate over your post.
I wish you'd follow your own advice.
It's not condescending. You're faced with a highly critical comment criticizing a whole framework when clearly the critic is completely oblivious to the most basic aspects of the whole domain. They know nothing about the whole problem domain, even failing to understand the most basic aspect of what they are doing or what they hope to achieve, but they still invest a lot of energy generating noise that's firmly in the "not even wrong" region. This serves anyone no good.
If you want to expand your knowledge beyond OAuth2 (and most probably you should if you want to design systems used by big guys from 0 to 1) , highly recommend to jump straight into OpenID Connect (OIDC) which is an identity layer built on top of OAuth 2.0.
Besides reading specs, Sascha Preibisch's videos on both OIDC and OAuth2 were the most useful to solidify a bigger picture for me
https://www.youtube.com/@saschazegerman/playlists
Specs are actually well written despite of all jargon and train of buzzwords used inside. The most annoying on my list are OP (OpenID Provider) and RP (Relying Party) ...
https://openid.net/specs/openid-connect-core-1_0.html
https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/
Most useful knowledge however personally gained from studying ORY Hydra mentioned in the article and Zitadel
The problem with OIDC and OAuth2 space - IDP providers are too "creative" in their interpretation of specs starting from userinfo and token exchange endpoints.
Without allocating significant amount of time getting all flows and related cyberops into your brain might never happened.
Good news - it's a life time investment ...
Oidc search on github gives good results - libraries, open source IDPs, all kind of proxies, etc
So, what we've learned is that OAuth2 is not a single thing, and that it is too complex.
This means that if you're working on a legacy application that's using something like the implicit grant, to actually learn about it, you need to read superseded RFCs.
Why do you think this is a problem? So old RFCs specify grant types. That's ok, that's the whole point of specifying authentication schemes. Some are not recommended? That's perfectly fine, it just means there are better, safer ways to implement a flow. Are they still widely use? That's great, you already know where they are specified. So what's the problem?
> This means that if you're working on a legacy application that's using something like the implicit grant, to actually learn about it, you need to read superseded RFCs.
I don't understand. Where do you see a problem? You said you know where a specific flow is specified, and you want to learn it. You even have a implementation? What's the problem? Does a "superseded" tag bother you?
OAuth specifies multiple authorization flows, each one including independent risk mitigation steps.
In my opinion OAuth2 is not "too complex". It's a subject matter that has intrinsic complexity, but one which isn't that high to be blunt.
Of course people who are oblivious to the subject and just glance at it from a distance might be tempted to dismiss it entirely as too complex. This is indeed a recurring problem in software development circles, where typically developers are too quick to criticize existing work because they don't understand requirements, are oblivious to the problem domain, and do not understand how the problems they don't understand are solved. But this doesn't mean the problem domain is complex or too complex.
There is a reason why this sort of walkthrough is very useful: those who are oblivious to the subject and just glance at it from a distance have a way to walk through the requirements and the happy flow in a easy-to-digest way. Hence the comments that now OAuth2 is actually not that complex, it's the RFCs that specify it that are the problem.
Unfortunately oauth cannot be compressed into a cheat sheet.
But yeah, oauth is absolutely something you forget right after using it and have to bootstrap every time you touch it.
What's so hard about a specific authentication flow?
You have a user, a client app, a resource service, and an authorization service. You have a sequence of requests that send data back and forth. The end result is a token that client apps can send to a resource service. What bit requires volumes to understand?
Take a minute to check RFC6749. All authorization flows in there require between 2 to 6 pages to fully define. Is this too much info to parse?
> GNAP (Grant Negotiation and Authorization Protocol) is an in-progress effort to develop a next-generation authorization protocol
From spec https://oauth.net/gnap/
> GNAP is not an extension of OAuth 2.0 and is not intended to be directly compatible with OAuth 2.0. GNAP seeks to provide functionality and solve use cases that OAuth 2.0 cannot easily or cleanly address.
> GNAP and OAuth 2.0 will likely exist in parallel for many deployments, and considerations have been taken to facilitate the mapping and transition from existing OAuth 2.0 systems to GNAP
Doesnt look like GNAP will fly any time soon, however there is a very interesting part - Security Considerations section. Looks like it was made by people who are familiar with all varieties of cyberops and usability issues in OAuth2/OIDC spec.
Security Considerations section
https://datatracker.ietf.org/doc/html/draft-ietf-gnap-core-p...
If any cyberops, pentester pro reading this, please advise how to research more. Thanx in advance.
If you're wondering what to use to get authentication working (and not doing something risky), 90% of the time the answer will be OIDC.
My personal answer is: a cheat sheet is enough.
I don't know oauth at all, but that was the area that always felt convoluted when i'd research it. I think i'd be much happier if they had sub spec names with very specific use cases. OAuth2 Client Redirect, OAuth2 Server Authority, or w/e.. i'm just making stuff up for attempted clarity.
Then I want an easy story for linking that instead to LDAP for corporate deployments, or to an SSO OAuth server.
The problem is...well I still don't really know how I should be including that? It's so much easier just to register a session cookie from a login page.
For a webpage this makes perfect sense, where would you securely store an access / refresh token on web that isn't vulnerable to XSS? In a session cookie that is secure & http only...
For native apps though that state might be more annoying to track and a auth token and refresh token is pretty easy to store securely.
Has this fallen through from an alternate dimension?
And if things require even a slim amount of thought and planning - chuck it to your favourite LLM and call it a day.
Just in case the sarcasm wasn’t clear I want to personally assure you that nobody ever will confuse an access token for an ID token. :p
Thankfully, just about every language and framework has OAuth2 libraries available so you can use it by copy/pasting four strings, whether it's a good fit or not. That's probably why it's overused as well, to avoid difficult integrations of simpler, custom schemes.
> However, it’s discouraged to use URL fragments as they impose potential security issues.
I'd love it if that linked to a footnote or similar that explained what those potential security issues are.
It doesn't have to be completely random, the spec only makes partial randomness a requirement:
"The binding value used for CSRF protection MUST contain a non-guessable value"
---
The state can be used to transmit useful data as long as the data isn't sensitive:
"The "state" and "scope" parameters SHOULD NOT include sensitive client or resource owner information in plain text, as they can be transmitted over insecure channels or stored insecurely."
This can be used in place of any 'Additional Client Callback URL params'.
---
Aside from that, I think this is very well written! I'll share it with others who want to learn more about OAuth 2.0 and its extensions.
Which explains why it's called "state".
Read the Controversy section: https://en.wikipedia.org/wiki/OAuth
With what we actually have, my impression (curious if others with more experience can confirm) is that you have to get lucky for different OAuth2 implementations to even be interoperable?
“Yo I heard you like URLs so I made URLs for your URLs.”
But seriously…if you’re going to have fixed URLs, why not just have fixed URLs for these endpoints? What does the indirection get you?
Also if you look at the typical endpoints you see listed there you'll find that they are usually pre-existing oauth2 endpoints that predate OIDC, so by not requiring the creation / new routing of those endpoints, OIDC adoption is easier on the OIDC provider side.
And lastly you'll need the metadata endpoint anyway for all the non-URL data that is exposed by that endpoint.
/.well-known/openid-configuration
to tell your the OAuth URLs, why not just require the OAuth URLs to be /.well-known/openid/authorize
/.well-known/openid/token
> by not requiring the creation / new routing of those endpoints, OIDC adoption is easier on the OIDC provider side.Redirects exist though. We already have the technology, we already have the protocols, we're just inventing more stuff that we already have.
Never saw a good example of how to implement a proper access to pdf or other downloadable documents.
What is your approach? Any good code base in open source to learn from?
Here’s a simple example using AWS S3 (or any S3-compatible storage) to generate a pre-signed URL for a PDF: https://github.com/pdfbolt/generate-s3-presigned-url
This works well for temporary document access in workflows like report generation, invoicing, and legal docs.
What if pre-signed URL is leaked, you cannot invalidate a pre-signed URL without rotating credentials or changing bucket policies, right?
I was thinking about signed cookies or API gateways type of solutions.
I’d go so far to consider this canonical. Bookmarked!
Or SAML. Had to implement SAML at work recently.
OAuth v1 was doing exactly the same, just different implementation detail (e.g. v2 relies on HTTPS, while v1 forced you to sign tokens so no need to encrypt).
voor bihas