[HN Gopher] The complete guide to protecting your APIs with OAuth2 ___________________________________________________________________ The complete guide to protecting your APIs with OAuth2 Author : mooreds Score : 153 points Date : 2022-04-12 16:34 UTC (6 hours ago) (HTM) web link (stackoverflow.blog) (TXT) w3m dump (stackoverflow.blog) | tptacek wrote: | It'd be useful to capture why OIDC exists (it addresses actual | vulnerabilities that crop up when you try to do OAuth as a | single-signon scheme rather than just as a way of delegating out | the ability to schedule a tweet with a 3rd party service), and to | pull out JWT --- you may not be able to avoid JWT if you're doing | OIDC, but it's helpful to know what problems JWT addresses and | what ones it doesn't, because if you can avoid JWT, you'll almost | certainly be better off. | paxys wrote: | The only real advantage of OIDC is that it enforces a strict | user structure, so different services can understand common | fields like id and email. The security aspects of it can all be | implemented with plain OAuth2 as well without the added OIDC | layer. | abraae wrote: | > In general, use the Authorization Code grant if there is a | human being involved and the Client Credentials grant if you are | performing server to server communication. | | This is the crux of the article. | | We're integrating with a vendor now that has imo chosen | incorrectly to use auth code instead of client credentials. | | This leads to several problems. One is that we need to store | their refresh tokens, which go stale after 2 weeks. Since it's | theoretically possible that the customer doesn't use the | integration for 2 weeks, we need to preemptively use the refresh | tokens ourselves behind the scenes every 2 weeks to prevent this. | When the vendor changes tech behind the scenes, they just chuck | away all existing tokens, so we then need to contact all | customers asking them to log in again in order to get new refresh | tokens. It sucks and it's brittle as hell. | | Tldr; don't use auth code grants (the ones most people think | oauth is) for server to server integrations. | weinzierl wrote: | For another quick way to get started with OAuth2, I can recommend | reading the 2.1 spec draft[1]. | | For a spec it is quite readable and pretty short. One reason for | this is that it _" [..] is an in-progress effort to consolidate | and simplify the most commonly used features of OAuth 2.0."_ [2] | | It does away with most of the complicated grants/flows of | previous version and basically boils down to just two[3]: | | - Authorization Code Grant | | - Client Credentials Grant | | Authorization Code Grant (which now implies PKCE) is what you | most probably want in most cases. So instead of complicated | decision trees[4] for most people it will be: | | "Learn one grant and be done". | | [1] https://datatracker.ietf.org/doc/html/draft-ietf- | oauth-v2-1-... | | [2] https://oauth.net/2.1/ | | [3] There is also the Refresh Token Grant, but it cannot be used | alone. There is also an extension mechanism to define new grants | and we will have to see if it is used. | | [4] https://alexbilbie.com/images/oauth-grants.svg | mooreds wrote: | Author here. | | Yes, I think that reading the OAuth 2.1 spec is a great place | to start. They've taken 10ish years of real world learning and | condensed it down. I first wrote about it 2 years ago[0] but | have been following along on the email list and they seem to be | getting closer and closer. I don't think it is at 'last | comment' yet, but I know they've done a lot of work. | | I am also excited about GNAP, which is a 'from scratch' attempt | to solve much the same problem. They've made some great | progress[1]. | | I briefly cover both of those in the article, in the "OAuth's | future" section | | 0: https://fusionauth.io/blog/2020/04/15/whats-new-in-oauth-2-1 | | 1: https://justinsecurity.medium.com/the-gnapathon-57ee110508ac | kache_ wrote: | I've got Opinions and Thoughts on OAuth2 (& all those other | protocols, SAML/OIDC) | | They all model sharing trust over to untrusted boundaries using | signed messages generated by one signing authority. There's | always a client, different clients have different properties, | they're trying to access a resource, and there is a privileged | signatory. | | Lots can be learned from their specs, but please don't limit | yourself to them, and don't even worry about following the spec | accurately (no one really does). Just know WHY the spec is | designed the way they are so that you avoid the same security | pitfalls. And understand WHAT you're doing: granting signed | assertions based on some user interactions | | Not only that, but just because it got through the IETF gauntlet | doesn't mean they don't have problems. These specs slide around | like crazy. My OAuth is different from your OAuth. The antidote? | Just write Good Docs and provide good libraries for your | integration path. A smart kid in a vacuum solving the same | problem OAuth solves will come up with OAuth. Try to emulate that | smart kid. And understand why certain concessions are made on the | protocols you're taking inspiration from because you might | actually not need to make those concessions | | This stuff hasn't been fully figured out, so push the needle | forward and don't be limited by the past. All protocols are | incorrect given a large enough time span. | mooreds wrote: | > A smart kid in a vacuum solving the same problem OAuth solves | will come up with OAuth. Try to emulate that smart kid. And | understand why certain concessions are made on the protocols | you're taking inspiration from because you might actually not | need to make those concessions. | | I have a different perspective. I work for an auth company now, | but before I did, I didn't want to think about this at all. | | I wanted to get some code shipped and build differentiating | features. | | I agree that the IETF and other standards bodies are not | perfect (there are specs that get published that never get | implemented widely and standards that are implemented that are | retrofitted specs). | | I do think that building on top of a spec is a great way to | "stand on the shoulders of giants", get access to people's | experience in use cases you haven't seen yet, and accelerate | your development effort. | | Also, there are a lot of folks who've written client libraries, | docs, and tutorials around OAuth that people can leverage. How | many devs will have experience with your "antidote"? I dunno, | but my guess is the number rounds to zero. | paxys wrote: | A smart kid implementing encryption from scratch could come up | with RSA or PKCS or EdDSA on their own. What's more likely is | that they will have major holes in their implementation that | decades worth of research in the area has already addressed. | | Similarly, while it is good to understand the various OAuth2 | RFCs and why certain decisions were made, you should also just | follow them instead of rolling your own auth exchange | mechanism. | kache_ wrote: | it would be great if everyone did "just follow them", but I | haven't seen a single spec compliant implementation in all my | years | lijogdfljk wrote: | I'm often frustrated by no clear OAuth-like system for non | general auth. Ie you have a server and a clientside JS app. How | do you secure it? Cookies are the obvious thing to reach for, | but in general i was never clear on exactly what the options | are. What are pros and cons of various types of | implementations? What are the do's and don'ts? And even if i | use something i often felt i was implementing all of it (due to | obscure languages choices frequently), but the specifics of the | impl were often difficult to find. | | It's embarrassing to say but auth has always confused me. And | of course managers always instantly say "Just use OAuth" -_- | mooreds wrote: | > you have a server and a clientside JS app. How do you | secure it? | | I'd love to hear what others have to say, but I'd suggest | encrypted session cookies. This is what some frameworks | support out of the box (rails has docs here: | https://guides.rubyonrails.org/security.html#sessions ). | Would store the session in an HttpOnly secure cookie. | | If you need to scale your server side horizontally, you'd use | redis, a database or something similar for your session | store. | | This feels like a problem usually solved at the framework | level (and has been for years) so maybe that's why there are | not as many "best practices" docs around? | | This OWASP document may be a useful read too: https://cheatsh | eetseries.owasp.org/cheatsheets/Session_Manag... | laerus wrote: | Wasn't there an on the making successor to OAuth2 from the same | people that was supposed to be a totally different take? I | remember hearing something about it but I cannot recall or find | the source. | mooreds wrote: | I think you are thinking of GNAP. The doc is still in progress, | you can see the 9th draft here: | https://datatracker.ietf.org/doc/draft-ietf-gnap-core-protoc... | (scroll down). | | I looked at it a year ago and wrote up some of the benefits: | https://fusionauth.io/blog/2021/01/07/gnap-next-gen-oauth | methyl wrote: | I think oauth is abused as a way of protecting your API. Often | it's just an unnecessary complication which makes your API harder | to use and your libraries bloated. | | If Stripe can get away with just public and secret key pair, | there is a big chance it's enough for you as well. | yoavm wrote: | I totally agree with you and so I'll put a shameless plug here: | I've created OAuth Hopper[0] exactly for this reason. | | It essentially takes a resource behind OAuth, strips OAuth from | it and exposes it with Basic Access Authentication. I'm using | it to let clients that don't support OAuth access services that | force it. | | [0] https://github.com/bjesus/oauth-hopper/ | [deleted] | gscott wrote: | Twilio as well | pbreit wrote: | Amen! I do not understand the rash of OAuth-style | authentication mechanisms for pure server-to-server | applications. | tremon wrote: | What user authentication does Stripe handle? As a user I've | interacted with Stripe's services a lot, but I've never needed | to authenticate myself to them. | pbreit wrote: | https://stripe.com/docs/api/authentication | | Even pure server-to-server applications with "no user | involved" are starting to use OAuth authentication which I | don't quite understand. | | https://www.verygoodsecurity.com/docs/payment- | optimization/a... | pbreit wrote: | Can someone explain the increasing usage of Oauth credentials for | pure server-to-server applications (like Stripe payment | processing)? | mooreds wrote: | I haven't worked with Stripe recently, but if I had to guess, | I'd say it is some combination of: | | * Time limited (rotation built in). | | * If using signed tokens, integrity of contents can be | verified. | | * Lots of libraries and knowledge around how to use it. | | * Tokens allow for more interesting/useful payloads than an API | key. | brap wrote: | As someone who has never used OAuth2 before, this article was not | helpful at all. Calling it a "complete guide" is a total | overstatement. | hotfixguru wrote: | I have also made an attempt at writing an article for | developers that want to implement Oauth2.[1] Not a complete | guide, but a short(8min) read that aims to get you started. | | [1]https://engineering.intility.com/article/implementing- | oauth2... | mooreds wrote: | Author here. | | @brap, sorry it wasn't helpful. It's aimed at folks who want to | protect APIs, but maybe I missed the mark. | | This article (which I co-authored) may be more helpful: | https://fusionauth.io/learn/expert-advice/oauth/modern-guide... | | It was also discussed here on HN, if you want some different | perspectives: https://news.ycombinator.com/item?id=29752918 | treve wrote: | Maybe calling it an introduction instead of a 'complete | guide' might quell some of this. | brap wrote: | I do appreciate the effort, and sorry for being a dick with | my earlier comment (bad mood). I do feel though that this | lacked concrete examples, and maybe should have taken a step | or two back to explain the more basic concepts. For example, | who owns the authentication service, is it me (the todos | developer) or a 3p? What exactly is the difference between | all of these different tokens? What's the actual protocol for | issuing and using them? Etc. I think something like a "Todos | API with OAuth2 from scratch with code snippets" could have | been super helpful for noobs like myself. | Traubenfuchs wrote: | Your sentiments and questions are all perfectly valid. I | believe the majority of developers implementing oauth2 on | their servers or integrating another service they need | oauth2 for have not fully understood what they are doing. I | know that's the case for me and I successfully implemented | solutions for OIDC, saml, three-legged oauth2 and two- | legged oauth2 on both the server and client. It's all an | overengineered mess. | | A "complete guide" to this is still sorely lacking -maybe | because it just is that complicated and can not be dumbed | down? | magicalhippo wrote: | Not op, but I found it a bit lacking given the title. From | the article: | | _While I'll dive further into how you actually use OAuth to | protect an API in your system below, including code examples, | [...]_ | | I failed to find much concrete around how to use OAuth to | protect an API, and no code samples. Is this a part one in a | series? If so, it should be more clear about that perhaps. | | edit: For example, I just had to secure my non-Azure API | using access tokens issued by Azure AD. Lot of details[1] | about how to verify that they're valid, actually issued by | Azure AD (one does not simply download a certificate), and | it's issued for the right thing. | | That said, I found the why and standards section very nice, | and the grant selection sections were helpful. | | [1]: https://docs.microsoft.com/en-us/azure/active- | directory/deve... | mooreds wrote: | > I failed to find much concrete around how to use OAuth to | protect an API, and no code samples. | | I think this may have been an oversight during the final | editing process. I ended up having to split this up into | two articles, as you surmised. | | The second one is a blow by blow of the authorization code | grant (and how an API should validate a token) and will be | published later this week. | | But I should have caught that we promised the code in the | intro and removed that. | magicalhippo wrote: | Just to expand a bit on my criticism. It's called a | "complete guide to protecting your APIs with OAuth", yet | there's no discussion of: | | - Authorization server, roll your own, run your own (like | Ory Hydra), or use third-party (like Azure AD)? | | - Tokes, if you can choose, should you go with opaque | tokens, JWT or something else? What about token lifetimes? | | - When you get a token from a client, how do you validate | that the token is valid? | | There's probably more, but I feel at least these points | should be included in a "complete guide". | | Change the title and it's a fine OAuth blog post. edit: for | example, add ", part 1 - introduction". | tbirdny wrote: | I can see the benefit of OAuth if you have an API that multiple | customers will use since it allows your customers to manage the | security themselves, to create and revoke tokens. I'm wondering, | is there any benefit to OAuth if the web service is for your own | company, between your own servers, even if the traffic goes over | the internet, compared to using a simple token in a header that | you generate by hand and the api checks for a match? | paxys wrote: | Between your own servers - not really. For that use case OAuth2 | will be just as effective as a single shared secret. | z3t4 wrote: | Am I the only one who thinks Oath is over-complicated bordering | to security through obscurity and vendor lock-in ? | | The protocol could be as simple as this (using password) | app => auth-server (can user:pass login to app?) auth- | server => app (no | yes) | | Or using "crypto": app => auth-server (can user | login to app ?) auth-server => app (only if user can | solve challange=XXXX with answer=YYYY) | | Asking for capabilities: app => auth-server | (what permissions do user have on app ?) auth-server => | app (user has access to: X, Y, Z) | paisawalla wrote: | First scenario: user's password can be captured and stored by | the app. | | Second scenario: could work if we're talking about a trusted | third party app (e.g. Authy) generating the response. Otherwise | presumably you enter your secret into the app, where the OTP is | derived. This has the same problem as above. | | Third scenario: no authentication required to query for | capabilities? _Puts on black hat_ Ok let me quickly check | [A-Z]{1,18}@whitehouse.gov and see which accounts I 'm most | interested in. | mooreds wrote: | Sure, if all you need to know is "can this user login" and you | don't have multiple servers that want to authorize the user, | you probably don't need OAuth. You can use sessions and | cookies. See my comment elsewhere in this post about this: | https://news.ycombinator.com/item?id=31007003 | | Interestingly, your first scenario is the resource owner | password credentials grant: | https://datatracker.ietf.org/doc/html/rfc6749#section-4.3 | | The second scenario is, I believe, the JWT bearer grant: | https://www.rfc-editor.org/rfc/rfc7523 | | Of course in the OAuth grants, the auth-server returns a token | to be presented to other resources instead of a "yes" or "no" | answer. | z3t4 wrote: | I was expecting how to implement OAuth2 in pseudo code or | JavaScript... | intrasight wrote: | Authentication is just one piece of the "protecting your APIs" | puzzle. Other pieces including rate-limiting and billing. Those | are more challenging. | suyash wrote: | Yes, also don't forget securing API credentials properly. As a | matter of fact, I have a blog post coming about this topic | soon. | mooreds wrote: | Would love to see it. Whether tokens or API keys, I'm always | interested in how folks recommend securing them. | | There's also some interesting stuff around token binding | happening. DPoP is moving towards becoming a standard: | https://datatracker.ietf.org/doc/html/draft-ietf-oauth- | dpop-... ___________________________________________________________________ (page generated 2022-04-12 23:00 UTC)