I love reading blog posts on oauth2 and oidc. I have a mental model on how it works but every person has their own way to describe the flows. So far my favorite article has been oauth-oidc from first principles[1] and why each piece of the protocol is useful.
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.
As a non-web person, I find everything related to this auth business 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 just use libraries without understand what actually provides the security.
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.
because web server, browser and protocol developers, after implementing HTTP Basic Auth punted and said this is gross and hard. They then gave up on the problem.
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).
Because web browsers are a massive hack and nothing works 100% so theres 10 different flows to cover which sort of broken is acceptable to your use case.
> 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).
> 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.
As an Oauth2 hater, I consider this protocol cursed, mainly due to how hard it is to read through all the specs and have a useful understanding of what one should do with it. Reading the OIDC spec, where they define authN in terms of authZ, lets me experience what a stroke must feel like.
I actually find it very readable. It was at least readable enough so I could implement an OAuth2 client from scratch in C# as a student.
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?
OpenID Connect is an extension to OAuth2 and a strict superset of it. All OpenID Connect servers are OAuth2 authorization servers - but not the inverse.
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.
Open ID Connect is not OAuth. It is not done as part of the IETF, and the OpenID Foundation seems to have slightly lower standards for specs. For instance, specs can be updated with errata sets that go as far as as introducing significant changes in the behavior without changing the version number and then do URL is just magically switched to the new document ("incorporating errata set N") without warning. And to top it off, there is no changelog to be found (or at least I couldn't find it).
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.
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.
Ha, I'm just reading this after tearing my hair out after trying to get a basic omniauth google login working in Rails. I was hitting CORS issues, for hours. I'm new to rails, but had read how productive it makes you. Well, thanks to one of their productivity features (Turbo) I was ready to throw the whole thing out.
Yes, I know, this wasn't an oauth2 issue directly. /rant :-)
Absolutely not. Read the specs [0] there as well if you truly want to know. XML canonicalization is a special kind of hell that I've done once and wish to never do again. And the enveloped signatures of xmldsig are also pretty complicated to get right. And it's a wild west as to how the specs are implemented on RPs and IDPs alike (more so, in my experience, than OIDC by a long shot).
Having just updated a project to use a newer version of the OpenSAML libs, this x1000. How something so fundamental can be so badly implemented (and documented!) is just mind-blowing.
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
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) ...
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
> 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.
> Apart from that, OAuth2 is such a vast area that we have been able to only answer the fundamental why questions and review the most popular delegation grants in this article.
So, what we've learned is that OAuth2 is not a single thing, and that it is too complex.
> So, what we've learned is that OAuth2 is not a single thing, and that it is too complex.
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.
OAuth's biggest issue is that unless you are regularly working with it, you'll probably forget most of the details once you're done implementing it. Similar story with regex for me, it's not that complex, but when I'm building queries a couple times a year at most, I end up forgetting it mostly. It's not surprising that most folks don't understand it, even if at one point they did in the past.
> Unfortunately oauth cannot be compressed into a cheat sheet.
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?
It's also hard to find the relevant RFC, because older RFCs contain grant types that are no longer recommended, but still widely in use.
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.
> It's also hard to find the relevant RFC, because older RFCs contain grant types that are no longer recommended, but still widely in use.
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 is authorization only. The part where it is vast is the different mechanics to grant/delegate access. And that's really needed because you need to be able to have Oauth working fo humans and machines where the accessing service can be the app on your phone, or some backend server.
I think they tried to make OAuth(2) too flexible, and to me the lesson -- and I wonder if this is commonly understood this way or not -- is that it's preferable to make very simple clear limited-scope standards for clear use cases, even if that means they won't be able to meet all use cases. And then add on (even possibly in additional separate standards) for other use cases, after the first has been succesful.
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?
OAuth2 is a very simple method to solve a very complex problem. Every part of it has a good reason to exist.
Unfortunately, OAuth2 is also used by applications that don't actually have the complex problems OAuth2 is trying to solve, which makes it look unnecessarily complex.
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.
One thing I wish I had learnt early on when I started looking into authentication is that OIDC (ideally with SSO through Google or GitHub) is the protocol/real-world implementation most developers will want to just be able to get started with whereas OAuth2 is more like the (boring) specification.
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.
OAuth2 is more general than OIDC, came first, and was intended to solve a smaller problem (delegated access to resources). OIDC is identity (rather than permission) implemented on top of OAuth2.
This is an excellent article. The only thing I am missing is a short paragraph about OIDC, which is the thing that enables authentication. To most people who just get in touch with the topic OAuth is more authentication than authorization.
very comprehensive but i wanted to add. oauth is one of those things i read about and forget 6 months later. there has to be a gamified way to make people learn about oauth and enforce it deep inside their brains
My problem is what part you're implementing can be different. Are you implementing the ability to use someone else as auth? Are you implementing the ability for others to use you as auth? Are you a client, or a server? etc
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.
My problem is that my use case is always this: by default the application should be it's own OAuth server, so the endpoints can use OAuth against the application and a local only database.
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.
> 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.
As with everything: repetition. If you forget these things you don't use them often enough. On that level, do you really need to remember them or are you happy enough to have a good and short reference, like this article for example?
> Practically speaking, the state is just a random non-guessable string that is saved in the client application session
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.
The best thing I can say about OAuth is that--as an identity dude--it keeps me gainfully employed. If only because people often implement it incorrectly.
Good breakdown! OAuth2 is one of those things that feels simple until you actually have to implement it. Curious how do you see OAuth2 fitting into workflows where users need to generate and securely access documents, like PDFs? We’ve found that balancing ease of access with security (especially for things like temporary document URLs) can get tricky.
Yeah, OIDC with session-based access makes sense, especially for enforcing policies dynamically. For secure PDF access, we’ve found pre-signed URLs to be a solid approach. They allow temporary, controlled access without requiring ongoing authentication.
You're right. Pre-signed URLs can’t be revoked once issued, but one way to mitigate the risk is by setting a short expiration time when generating them. For example, if the URL is only valid for 5-10 minutes, it remains secure, and the risk of misuse is minimal.
> Have you ever logged into a website using your Google or Facebook account? Or connected an app to access your GitHub data? If so, you’ve already used OAuth2, whether you knew it or not.
Very good presentation but I do miss any mention of the audience claim. This claim is underrated in my opinion at least. It allows the token to climb access to an api or server or whatever that can be used by gateways to do a high level authorization. Then the scopes can be used at the resource server to govern lower level authorization.
It always says OAuth2, even though it's all about OAuth in general.
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).
> So they generalize the discovery approach from OpenID Connect specification into RFC8414 that adds a new metadata route under .well-known subpath.
That route contains URLs of the authorization and token endpoints, supported token authentications, OpenID user URL, etc.
“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?
The indirection gets you simplicity during integration, as in the optimal case the consumer only has to point to a single URL than to a handful, and rest of the URLs can be auto-discovered from there.
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.
my guess the idea and intension of .well-known was good, so generic end-user libraries can be implement ... the reality is ugly and generate lot of man hours for cyberops consultancies
I love reading blog posts on oauth2 and oidc. I have a mental model on how it works but every person has their own way to describe the flows. So far my favorite article has been oauth-oidc from first principles[1] and why each piece of the protocol is useful.
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.
[1] https://stack-auth.com/blog/oauth-from-first-principles
If you love it so much, here is another one: https://blog.ce9e.org/posts/2025-01-07-oidc/
As a non-web person, I find everything related to this auth business 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 just use libraries without understand what actually provides the security.
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.
because web server, browser and protocol developers, after implementing HTTP Basic Auth punted and said this is gross and hard. They then gave up on the problem.
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).
Because web browsers are a massive hack and nothing works 100% so theres 10 different flows to cover which sort of broken is acceptable to your use case.
> 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).
> As a non-web person,
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.
>i want the user to do this very particular thing in an absolutely correct way
good luck
As an Oauth2 hater, I consider this protocol cursed, mainly due to how hard it is to read through all the specs and have a useful understanding of what one should do with it. Reading the OIDC spec, where they define authN in terms of authZ, lets me experience what a stroke must feel like.
I actually find it very readable. It was at least readable enough so I could implement an OAuth2 client from scratch in C# as a student.
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?
OpenID Connect is an extension to OAuth2 and a strict superset of it. All OpenID Connect servers are OAuth2 authorization servers - but not the inverse.
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.
Open ID Connect is not OAuth. It is not done as part of the IETF, and the OpenID Foundation seems to have slightly lower standards for specs. For instance, specs can be updated with errata sets that go as far as as introducing significant changes in the behavior without changing the version number and then do URL is just magically switched to the new document ("incorporating errata set N") without warning. And to top it off, there is no changelog to be found (or at least I couldn't find it).
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.
[1] https://oauth.net/2/oauth-best-practice/
[2] https://oauth.net/2/browser-based-apps/
> Some specs should be mandatory 100% agree
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.
Some of the worst times I have had in projects are when I've had to add oauth2.
Ha, I'm just reading this after tearing my hair out after trying to get a basic omniauth google login working in Rails. I was hitting CORS issues, for hours. I'm new to rails, but had read how productive it makes you. Well, thanks to one of their productivity features (Turbo) I was ready to throw the whole thing out. Yes, I know, this wasn't an oauth2 issue directly. /rant :-)
Is SAML any better?
Absolutely not. Read the specs [0] there as well if you truly want to know. XML canonicalization is a special kind of hell that I've done once and wish to never do again. And the enveloped signatures of xmldsig are also pretty complicated to get right. And it's a wild west as to how the specs are implemented on RPs and IDPs alike (more so, in my experience, than OIDC by a long shot).
[0] https://www.oasis-open.org/standard/saml/ or https://saml.xml.org/saml-specifications
(I know, agreed. Rhetorical.)
No. I think SAML(/Shibboleth) was a big influence to OAuth2 (?) and is probably the source of most of what ails OAuth2.
SAML is much, much worse than OIDC.
https://news.ycombinator.com/item?id=28080553
Give it a try and try to come back with your sanity intact. I dare you :)
It's mess.
Having just updated a project to use a newer version of the OpenSAML libs, this x1000. How something so fundamental can be so badly implemented (and documented!) is just mind-blowing.
Excellent writing and diagrams!
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
https://zitadel.com/
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
https://github.com/topics/oidc
And by the way, has anyone researched on GNAP (published 20 March 2024)?
> 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.
> Apart from that, OAuth2 is such a vast area that we have been able to only answer the fundamental why questions and review the most popular delegation grants in this article.
So, what we've learned is that OAuth2 is not a single thing, and that it is too complex.
> So, what we've learned is that OAuth2 is not a single thing, and that it is too complex.
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.
OAuth's biggest issue is that unless you are regularly working with it, you'll probably forget most of the details once you're done implementing it. Similar story with regex for me, it's not that complex, but when I'm building queries a couple times a year at most, I end up forgetting it mostly. It's not surprising that most folks don't understand it, even if at one point they did in the past.
There are one page regex cheat sheets you can print out and put in your workspace. Then you simply consult the cheat sheets.
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.
> Unfortunately oauth cannot be compressed into a cheat sheet.
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?
https://datatracker.ietf.org/doc/html/rfc6749
That matches my experience, and it doesn't help that the RFCs, in trying to explain it, have declared defeat early on.
It's also hard to find the relevant RFC, because older RFCs contain grant types that are no longer recommended, but still widely in use.
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.
> It's also hard to find the relevant RFC, because older RFCs contain grant types that are no longer recommended, but still widely in use.
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?
The oauth 2.1 spec does a lot to bring everything together and simplify things at the same time.
OAuth is authorization only. The part where it is vast is the different mechanics to grant/delegate access. And that's really needed because you need to be able to have Oauth working fo humans and machines where the accessing service can be the app on your phone, or some backend server.
I think they tried to make OAuth(2) too flexible, and to me the lesson -- and I wonder if this is commonly understood this way or not -- is that it's preferable to make very simple clear limited-scope standards for clear use cases, even if that means they won't be able to meet all use cases. And then add on (even possibly in additional separate standards) for other use cases, after the first has been succesful.
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?
> OAuth2 is built to be super simple to implement client applications
Has this fallen through from an alternate dimension?
OAuth2 is a very simple method to solve a very complex problem. Every part of it has a good reason to exist. Unfortunately, OAuth2 is also used by applications that don't actually have the complex problems OAuth2 is trying to solve, which makes it look unnecessarily complex.
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.
No you misunderstand- it is super simple to pay some other company a small amount to do this for you. No complexity to worry about what so ever.
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
Or a refresh token (which might be one of those two you mentioned)
One thing I wish I had learnt early on when I started looking into authentication is that OIDC (ideally with SSO through Google or GitHub) is the protocol/real-world implementation most developers will want to just be able to get started with whereas OAuth2 is more like the (boring) specification.
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.
OAuth2 is more general than OIDC, came first, and was intended to solve a smaller problem (delegated access to resources). OIDC is identity (rather than permission) implemented on top of OAuth2.
This is my absolute favorite explanation of OAuth 2: https://stackoverflow.com/questions/4727226/how-does-oauth-2...
No discussion of OAuth2 can be done without mentioning it's cursed origins.
Read the Controversy section: https://en.wikipedia.org/wiki/OAuth
This is an excellent article. The only thing I am missing is a short paragraph about OIDC, which is the thing that enables authentication. To most people who just get in touch with the topic OAuth is more authentication than authorization.
very comprehensive but i wanted to add. oauth is one of those things i read about and forget 6 months later. there has to be a gamified way to make people learn about oauth and enforce it deep inside their brains
If you implement it twice, the sequence diagram tends to get burned into the brain. It’s tricky and you’ll be able to anticipate its trickiness.
My problem is what part you're implementing can be different. Are you implementing the ability to use someone else as auth? Are you implementing the ability for others to use you as auth? Are you a client, or a server? etc
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.
My problem is that my use case is always this: by default the application should be it's own OAuth server, so the endpoints can use OAuth against the application and a local only database.
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.
> 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.
As with everything: repetition. If you forget these things you don't use them often enough. On that level, do you really need to remember them or are you happy enough to have a good and short reference, like this article for example?
My personal answer is: a cheat sheet is enough.
> Practically speaking, the state is just a random non-guessable string that is saved in the client application session
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.
And this is why OIDC and IDPs exists to expand more with nonce, user agent footprints and other validation mechanisms
> The state can be used to transmit useful data...
Which explains why it's called "state".
Feature request: at one point in this guide it says:
> 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.
If the user is on a search page, the user's query (which could be argued as private/sensitive data) would be exposed. That's one I can think of.
The best thing I can say about OAuth is that--as an identity dude--it keeps me gainfully employed. If only because people often implement it incorrectly.
Good breakdown! OAuth2 is one of those things that feels simple until you actually have to implement it. Curious how do you see OAuth2 fitting into workflows where users need to generate and securely access documents, like PDFs? We’ve found that balancing ease of access with security (especially for things like temporary document URLs) can get tricky.
Expand to OIDC and use session based mechanism with some kind of policy engine?
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?
Yeah, OIDC with session-based access makes sense, especially for enforcing policies dynamically. For secure PDF access, we’ve found pre-signed URLs to be a solid approach. They allow temporary, controlled access without requiring ongoing authentication.
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.
Thanx for sharing!
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.
You're right. Pre-signed URLs can’t be revoked once issued, but one way to mitigate the risk is by setting a short expiration time when generating them. For example, if the URL is only valid for 5-10 minutes, it remains secure, and the risk of misuse is minimal.
It’s this one thing no one implements correctly ;)
> Have you ever logged into a website using your Google or Facebook account? Or connected an app to access your GitHub data? If so, you’ve already used OAuth2, whether you knew it or not.
Or SAML. Had to implement SAML at work recently.
Is oauth the thing that brought on us those applications that have to open a browser window to authenticate you?
This is by far the most elegant and thorough write up of OAuth2 I’ve ever read.
I’d go so far to consider this canonical. Bookmarked!
Very good presentation but I do miss any mention of the audience claim. This claim is underrated in my opinion at least. It allows the token to climb access to an api or server or whatever that can be used by gateways to do a high level authorization. Then the scopes can be used at the resource server to govern lower level authorization.
It always says OAuth2, even though it's all about OAuth in general.
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).
Well, it’s still more approachable than SAML. Our industry is messed up and we wonder why phishing is still a thing.
It’s funny to see your co-worker make the front page of hacker news.
What about…a friend?
> So they generalize the discovery approach from OpenID Connect specification into RFC8414 that adds a new metadata route under .well-known subpath. That route contains URLs of the authorization and token endpoints, supported token authentications, OpenID user URL, etc.
“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?
The indirection gets you simplicity during integration, as in the optimal case the consumer only has to point to a single URL than to a handful, and rest of the URLs can be auto-discovered from there.
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.
My point is that if you require
to tell your the OAuth URLs, why not just require the OAuth URLs to be > 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.
my guess the idea and intension of .well-known was good, so generic end-user libraries can be implement ... the reality is ugly and generate lot of man hours for cyberops consultancies
It's the manifested fear of AOLesque internet silos to hang on to their ~prey~ users by the claw. It creates a less open, less federated web.