6 ms·
It'd be interesting to hear about people who have had a good time implementing OAuth, as my experience is similar to that in the article. I've played with addin
by remus 3y ago
It'd be interesting to hear about people who have had a good time implementing OAuth, as my experience is similar to that in the article. I've played with adding it to a few side projects and the process usually goes:
1. Read loads of docs, end up pretty confused
2. Find a library that seems to do what I want
3. Install this huge library full of opaque code
doing...things
4. Have an impossible time troubleshooting issues
5. Get scared ("I'm almost certainly doing something wrong here") and give up
I find it hard to have much faith in security standards like this. I want them small, well defined and understandable and OAuth does not meet any of these criteria in my experience.
- zippergz 3y ago3b. realize that library is deprecated or hasn't been updated in many years and is either totally broken, or incompatible with something else you're using.
- Spivak 3y ago3c. Write your own "library" which encompasses the the 50 lines of code. Adding the oauth calls into your app that already has a web server, job processing, and a db is way easier than integrating what ever weird stuff some random library does.
- btilly 3y agoI have read many docs. The one that I find easiest to understanding is still the one that I wrote about a decade ago when I first had to work with OAuth 2. All others I understanding by mapping what they said to concepts in mine, and that seems to work pretty well. My document is available at https://metacpan.org/dist/LWP-Authen-OAuth2/view/lib/LWP/Authen/OAuth2/Overview.pod https://metacpan.org/dist/LWP-Authen-OAuth2/view/lib/LWP/Aut.... Even though you're unlikely to ever use that library or language, you may find it worthwhile.
- sebmellen 3y agoI'm pretty astounded, because this is by far the best OAuth 2 doc I've ever read, and that's after reading and watching many hours of content from leaders and companies in the space.
- btilly 3y agoThank you. It summarized my understanding after a month of reading documentation, doing experiments, and generally banging my head against the wall.
- mixmastamyk 3y agoLooks great, taking a look and favoriting. (Only feedback I can think of is that it would be great to have a few diagrams... like from excalidraw or something. Am largely a visual learner.)
- interroboink 3y agoAs a fan of Perl, this situation of having an obscure, meticulously-documented CPAN module to not only explain but implement some common-but-surprisingly-hard pattern is just so ... Perl-y (: Perhaps it's a semi-consequence of Perl being perceived as old and crusty, and popular with old crusty people who are merely trying to get things done without fluff (at least speaking for myself). Reminds me of Data::Manip, another favorite of mine. Thanks for taking the time to write this (and implement all that nonsense).
- btilly 3y agoThanks. The crustiness in this case was enhanced by my grumpiness over some frustrating debugging sessions, and having to go through a lot of very confusing documentation to get there. That grumpiness shows through in a couple of places. For example I understand why Google decided that I was asking for the same permission too often, and began handing me codes that would not work. And also wouldn't explain what was wrong with the code that I just got.
- count 3y agoPlease publish this on its own somewhere! This is fantastic.
- adammarples 3y agoI'm bookmarking this to go through the next time I need to bang my head against this wall, thanks
- jkubicek 3y agoYour documentation is amongst the best I've seen on OAuth, but it suffers from the same naming confusion I always run into when I'm reading OAuth docs. > OAuth 2 makes it easy for large service providers to write many APIs that users can securely authorize third party consumers If I'm trying to write a Mastodon client, I'm reading this line piece by piece: > OAuth 2 makes it easy for large service providers "service providers" OK, that must be the Mastodon service. > ... to write many APIs that users "users" That must be me > ... can securely authorize third party consumers "consumers" OK... that's also me?
- Operyl 3y agoUsers are your users shared with the users of that API service (which may include you if you use your own service), consumer in this case is you (the application you're running).
- btilly 3y agoThat is why there is a terminology section: https://metacpan.org/dist/LWP-Authen-OAuth2/view/lib/LWP/Authen/OAuth2/Overview.pod#Terminology https://metacpan.org/dist/LWP-Authen-OAuth2/view/lib/LWP/Aut... If you're trying to write a Mastadon client, then the Mastadon service is the service provider, you are the consumer, and the people who wish to use your client are the users.
- mekoka 3y agoI think it's helpful to not stray too far away from the standard terminology. I found that "third party" was an excellent indicator that the consumer is probably not me, especially since I've already qualified as a user.
- pcthrowaway 3y agoRead the introduction again, and then follow the link to the Terminology section.
- pcthrowaway 3y agoThis is the first Oauth document I've seen with a no-nonsense "Terminology" section. Thank you! The only thing I'd suggest is putting the terminology first, so readers can first correct their misconceptions from all the terrible literature around this.
- btilly 3y agoI thought about it, and settled on the compromise of referring to it up front, and then putting it at the end. That's because there are many ways you could use a document like that. And the Terminology section is very overwhelming unless your goal is to understand how OAuth 2 REALLY works, and why it works that way.
- butisaidsudo 3y agoI read so many docs when I was trying to implement OAuth and got more and more confused. This video was a huge help though for explaining all of the concepts: https://www.youtube.com/watch?v=996OiexHze0 https://www.youtube.com/watch?v=996OiexHze0
- missingdays 3y agoOAuth specification was the best source for me. All provider docs are simplified and usually specific to the provider
- chasd00 3y agoIt’s been a while since I’ve read the RFCs but I recall them being very accessible and clearly written.
- klabb3 3y agoWe really deserve a less over-engineered actual standard that has a very restricted feature set. In practice, isn’t OAuth predominantly used to verify proof of email ownership? If so, why not just use magic links as sign up & sign in? 1. Sign in/up: Enter email (can be pre-filled by browser/app) 2. Click the email verification link or enter code if on different device. 3. Profit. No manual typing necessary, only clicks. This is trivial to implement, and can be extended in the future with a simple standard for browsers/apps to automatically verify in the background (to avoid the tab-switching inconvenience in step 2). On iOS they auto-populate SMS codes in a similar fashion. 2FA can be out of scope, (many times not needed because email providers already have it). But if needed, it can be added as a second step after the email proof. Please tell me what I’m missing. This seems, to me, like an excellent trade off between implementation simplicity, extensibility, user convenience and security.
- p_l 3y agoIt would simply not handle pretty much any case that I have used OAuth2 to implement so far. For example - login system that merged LDAP/Kerberos/client cert/long-lived application token authentication into single system, that also linked said authentication system into all applications in the network, including making it possible to login to AWS Console using Kerberos (that one was twisty to get running, not because of OAuth2 but because of how it is handled by AWS IAM). Also, I have used it to link in MFA systems of different kinds (it was definitely easier side than industry standard of using Radius) In addition, this proposed system requires that every app has ability to send emails, which honestly is less simple than it sounds, especially today when sending to arbitrary public emails.
- klabb3 3y agoFor service accounts, email is clearly not the right choice. I don’t have experience with enterprise auth, are Kerberos etc not using company email for human identity? > this proposed system requires that every app has ability to send emails, which honestly is less simple than it sounds For humans and especially end-users of consumer services, my observation is that the elaborate auth dances are using email ownership as last resort anyway, ie for account recovery and/or a trusted 3p that has verified the email. So the thought is simply to make that flow more convenient. Perhaps this is misguided.
- titaniczero 3y agoMy experience is similar but tbh I feel it's mainly due to the fact that oauth is implementing an important security layer (authentication/authorization) and that's hard by definition. There are lots of steps and things you can't afford to overlook or you'll be vulnerable to multiple different attacks
- tarsinge 3y agoI found doing a custom (without a library) OAuth integration for only one service relatively straightforward, i.e. when it’s not treated as a standard. For example for a plug-in exclusively for Shopify (random example, didn’t try it) you would just treat it as the rest of their API and write custom code. In short it works when you can see it as a guideline instead of a standard.
- Aeolun 3y agoWhen I stopped using libraries and implemented my own things got a lot less frustrating. Still a pain in the ass, but I didn’t feel like the errors came out of nowhere any more anyway.
- magicalhippo 3y agoYeah I've just implemented it myself. Google, Microsoft and some other OIDC provider. I abstracted it away behind a "token provider" interface, so I can just instantiate the right one for the job. There's some incantations to get the request right, but I found most documentation decent so just follow that. One service required I implemented RFC 8693 token exchange, which turned out to be trivial since I could represent it as one "token provider" instance wrapping another. Failures can still be opaque though, especially when using the tokens.
- madeofpalk 3y agoI've reimplemented oauth for the same provider (bungie.net) countless times. I think it might seem daunting, but when you break it down into the steps it's pretty simple: - Send user to example.com - Eventually they're sent back to yoursite.com with a ?code=abc - Call example.com/OAuth to exchange ?code=abc for access token and refresh token - You're done (for now) - When access token expires, call example.com/OAuth to exchange refresh token for a new access token and refresh token The tricky part is that a bunch is implementation specific, so memorising the above only gets you half way to implementing with another provider.
- chasd00 3y agoYeah I don’t see what the big deal is. You don’t need to know every oauth flow by heart and most of the time you’re going to be using the authorization code flow anyway. There are tons of articles and comments on HN about much more complex things than oauth every day.
- elevation 3y agoI have an application with this flow already implemented to authenticate a user. But the application currently has it's own authorization policy in a flat file which organizes users into groups and gives groups permission to take certain actions, a simple RBAC. I'd like to refactor this so that the authorization is delegated to the OAuth server. Ideally I want to be able to ask a keycloak/okta server "now that user X is authenticated, are they part of the group Y?". Since this isn't a common use case and everything is so abstract it's been very difficult to find an obvious path forward.
- ksm 3y agoI had bit similar need when implementing our own OAuth2 authorization server to be used by our own (three) web applications and several APIs related to them, all of which use the same backend to store users and API keys with differing permissions to logical entities our datamodel consists of. These permissions are somewhat naturally mapped to scopes, but the main issue is that single user or API key could have differing permission across multiple logical entities, so it's M-to-N representation (M logical entities, with N different scopes). So simple returned scopes would not suffice, as resource server needs to know which entity or entities the caller also has access to, according to scopes. As I could not find any pre-existing good guidance on solving this, I ended up implementing it by having the resource servers (i.e. APIs) check the token using token introspection endpoint at the auth server (not the RFC version of introspection, just private one for now but I may add the RFC compliant version as well so it could be called by 3rd parties as we have not yet rolled out this OAuth2 based setup for our customers). Part of that return information from the introspection endpoint is this permission mapping between logical entities and scopes, so the resource server can know to which entities caller has which scopes. Of course, as our access tokens are not JWT and just opaque (encrypted) data, the introspection endpoint then need to decrypt it - just so it can quickly validate expiration etc. - and if valid, fetch a matching copy from the database that has more contextual information than what's encoded inside the client-supplied access token. Otherwise, the length would be prohibitive if token would be fully self-contained with these extra information. Maybe this same kind of method could be used for your use case as well, encoding authorization policy adjacent to the access token in your backend, and looked up by app using it after it has received the token?
- magicalhippo 3y agoI've both had to acquire and validate[1] tokens from Azure AD, both Client Credentials[2] and Authorization Code[3] flows, and found Microsofts documentation quite good. I've also had to acquire tokens using certificate-based Client Credentials flow from another party. Overall I found it fairly OK, it's a bit of a learning curve when you're just used to basic user/pass, but it's fine. However the main issue is that when it's not working it's very opaque. This is even worse when trying to _use_ the tokens. I spent many hours trying to figure out why my Client Credentials tokens wouldn't work for logging on to Office365's IMAP server, only to spend half an hour searching and finding some Microsoft community forum post saying it wasn't implemented yet... they only supported Authorization Code flow. This has been fixed they say, I'll know later today cause that just came up as a priority ticket... All you get back is some "nope", with no way to figure out why. [1]: https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens https://learn.microsoft.com/en-us/azure/active-directory/dev... [2]: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow https://learn.microsoft.com/en-us/azure/active-directory/dev... [3]: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow https://learn.microsoft.com/en-us/azure/active-directory/dev...
- gpspake 3y agoI had a good experience when I went in to a project with the attitude that "Ok, I'm going to wire up auth0 in perfect accordance with how they want me to, absolutely from scratch with the most perfect clean official documentation/library (in my case the react auth0 sdk) conforming approach possible. I spent a lot of time making sure I did everything as by the book as possible and , in the end, I had a good experience and felt confident in my implementation, and like I understood all the moving parts. I even got help in a SO thread from an auth0 employee. Auth0 could have been anything, here... On the same project, I kind of did the same thing with vite/react/tailwind client and fast api backend where I touched every piece of it, made every decision, and made sure I was really confident. This was in my own little vacuum where a big part of the app was just creating my perfect little sandbox. Stuff gets way more complicated when you have to hustle to get stuff over the line or you're trying to cram so new auth implementation in to an 8 yr old app that's been walked around on by dozens of engineers slamming out slop to close a ticket. (Note: I know auth0 is a little more on-rails than implementing auth0 without it. They tend to have pretty good guides if you're using current hotness like react or fastapi)
- asdfman123 3y agoMy preferred development style is 1) skimming for limited context 2) copying and pasting random code 3) trying it with print statements 4) getting stuck 5) repeating steps 1-3 until it works
- sytringy05 3y agoIt's interesting to hear that because IHMO one of the reasons OAuth and JWT took over the world is that you can base64 decode the tokens and see whats inside them, compared to Kerb or NTLM which you eventually learn to spot based on their binary headers or whatever (eg NTLM tokens in HTTP Headers always start with "TRIM" for some reason) I get the problem though, many of the libraries are not great or simply difficult to use
- vbezhenar 3y agoWell, my experience is like install keycloak, configure some framework plugin (like Spring Security) and that's about it... I have rough understanding of oauth but never had to dive in.
- knallfrosch 3y agoYeah, pretty much. We have a hidden iframe silently refreshing tokens. Don't ask me why, I thought the whole point of OAuth was that example.com was allowed to access identity.com. Instead, example.com opens a hidden identity.com iframe and does what do I know? At my old job, users could specify their own IdentityProvider for their instance, which added a whole layer of complexity. Now we have found out that a different team has implemented their side of OAuth completely wrong: Their device flow ("Open in app and enter 56474") doesn't poll automatically. Instead, user have to click "try now" manually. The whole auth is lost when the device restarts. I'm not surprised Microsoft lost control of Bing because they implemented OAuth wrong for one of the services displayed there.
- snapetom 3y agoAnd each provider you intend to support exponentially clutters up code in the frontend and your /authenticate endpoint in the backend. Imports for each one, IF/ELSE statements to handle each one.