Hacker News new | past | comments | ask | show | jobs | submit login
A guide to Oauth2 (milapneupane.com.np)
254 points by milap on Sept 2, 2019 | hide | past | favorite | 53 comments

I'm currently in the middle of implementing an OAuth 2.0 authorization server following the RFC draft of the best current practice [1].

It's been a huge pain navigating all the interlinked (and sometimes contradicting) RFCs around, especially with a distinct lack of resources for actually implementing an authorization server. RFC6749 does not suffice on its own since it says nothing about authentication or tokens payload (not that it should). I did discover the whole RFC universe which are mostly fascinating and very well written.

Most google searches end up to Auth0 (nice SEO!), which I'm sure is a fine product, but usually only gives a very high-level overview of the corresponding spec and ends up like "see how this is all complicated? there's a SAAS for that...".

I'm seriously considering implementing a fully spec-compliant OAuth 2.0 + OpenID Connect Core 1.0 reference server implementation in Typescript, with full documentation quoted straight from the RFCs. The HOW is actually pretty straight-forward once you've figured out the WHAT and WHY.

[1] https://tools.ietf.org/html/draft-ietf-oauth-security-topics

IMO, the python oauthlib does a really good job of this. they include the relevant sections of the spec into the function documentation so you can follow along:


Me and my team are happy users of keycloak[0] running in a docker swarm, pretty nice so far anf very good documentation. Building your own authorization/authentication solution is really nice as you learn a lot, but there is a lot of work involved. [0] https://github.com/keycloak/keycloak

> I'm seriously considering implementing a fully spec-compliant OAuth 2.0 + OpenID Connect Core 1.0 reference server implementation in Typescript

That'd be awesome - I'd appreciate learning from something like that, and I really appreciate Typescript

I’m actually working on the same thing but in Rust. If you ever want to compare notes sometime, give me a shout out.

I’m actually kind of glad the documentation found via google searches (save one collection of Medium articles) has been disappointing. It has motivated me to look directly at the specification which I’ve found to be the most valuable resource thus far.

Oh yeah definitely!

Rust would be awesome but I think I'd want it to be as accessible as possible. Tagged unions and proper error handling would make it much saner though that's for sure.

I was initially going to do it in TypeScript, as the clients that will be interacting with it are TypeScript. Can’t really go wrong either way, but yeah, I’ve enjoyed exploiting Rust’s type system!

Be careful to do the hard stuff in workers, otherwise your throughput will be limited by one core.

Sorry if that's so basic of a consideration that it's insulting, but I've seen it done before.

Which medium collection? I’d like to read to refresh my knowledge

This is a great exercise. It's really fulfilling to learn a spec by implementing.

I've used @panva's certified [0] js provider [1] and client [2] for many use cases. Is there a reason (aside from learning) to reimplement the spec? If you do, you may consider getting your implementation certified to expand the list!

[0] https://openid.net/developers/certified/ [1] https://github.com/panva/node-oidc-provider [2] https://github.com/panva/node-openid-client

I'd love to see RFCs return back to one goal, one RFC. These days we have RFC ivory towers where they make a base spec, and 7-8 implementation option specs. All separate RFCs. Very horrible. (edit a goal being a complete thing: oauth2)

I would love to see a reference server implementation for OAuth 2.0 & OpenID Connect Core 1.0, as it would be quite helpful when I go to add OAuth 2.0 to the libre software suite we use at work!

May be worth checking out https://github.com/ory/hydra and related projects by ory

It's worth mentioning that it's a bad idea to invalidate refresh_token grants ever during the lifetime of an authorization. I've seen APIs do this immediately upon sending the response to the token endpoint, which makes the system unusable due to the frequency of network transmission errors that would result in having to contact the resource owner to grant access again. Even an expiry after days and years is only likely to result in more support requests to the API maintainer without increasing security enough to justify it.

The reason this bad practice is common is that it is allowed by the spec in https://tools.ietf.org/html/rfc6749#section-6 as an optional action to take on refresh grants. Please, do not do this.

I've always believed it should be the responsibility of the consumer (perhaps with the aid of client libraries) to properly handle the refresh lifecycle. I'm not a fan of password rotation, generally speaking, but it's because humans are terrible at remembering and creating complex passwords. Software processes don't have the same problem.

"sending the response to the token endpoint" Which response?

"makes the system unusable due to the frequency of network transmission errors that would result in having to contact the resource owner" What kind of network transmission errors are you getting? And at what quantity? This shouldn't be too difficult to do

I disagree and think refresh_token expirations do add to security and believe it is the client's job to handle any difficulties that can come with the expiration period

I don’t think I saw a support ticket in years around refresh tokens and we definitely expired them to avoid storing an infinite history of the things. And also a nagging sense of not increasing account token leakage.

Tl;dr: I don’t know kids, seemed fine to me, world didn’t end

> You want to add all your contacts in Gmail who are in skype

Never once in my lifetime I wanted to do that. For any two services.

Above that I think this is rude to my contacts: You can’t just go and upload random people’s data on plattforms of your choice.

I get it – people feel like it is their contacts because they collected them, but they are not. This should be illegal.

It would be ridiculous to make something like that illegal. Contact information shared with an individual DOES give that individual the freedom to use the information how they'd like. Hopefully whoever shared their contact information in the first place is okay with their information being stored with Apple or Google since that is the default way many people back up their contacts. If the contact sharer is not okay with it the onus is on them to vet who it is they're sharing their information with.

So you don't store numbers of any of your contacts? You must have some insane memory ... but then again ... maybe memorizing random people's data should also be illegal... I mean did the people who told you those details give you permission to memorize it? I think not. And when you enter those memorized details into your browser or phone ... who gave you permission to do that?! Blatant GDPR violations.

If only there was some way to store contacts without uploading them..

Has it really come to this? If you open your phone now you usually have two offline options: to store contacts on the SIM card and to store them on the phone.

If you want backups and comfort without betraying your contacts you run your own nextcloud instance and store them automatically on there.

That's why my dream contact platform would feature client side encryption. We should have a bitwarden/lastpass/1password for contacts, that synchronizes it across my services and devices, with a solid API + permission scheme to share with other apps.

I currently have at least 6 places where my contacts are stored (should I say scattered). I have no way to search them all, tag them all, archive the ones I seldom need, have versioning of the various data, etc.

Besides, contacts are a very broad topic.

I have contacts for friend and families, I have girls I'm flirting with, I have clients, I have administration offices, hair cutters, providers, restaurants... For some of them I want a way to contact them, some of them the location, some I don't want to appear in the main listing, some I want to explicitly hide from people peeking at my phones, some I want to easily share or even synchronize with others.

And then there is the way things are labelled. When going networking, I will collect many contacts I want to isolate. I want to be able to search them from a "known from" fields, or a "industry" tag. I want to make groups to mass communicate: I organize parties and sport events, and the best way to get people on board is still direct texting, and optional calling: fb events don't cut it.

It's one of those simple topics that aren't solve.

There is still no simple way to just send files from any computer to another. Try telling your mum to send you this videos from their iPhone to your laptop now that the wifi is down. Or share 3Go of photos with this group of 20 persons you just met on a trip.

There is still no simple way to make check lists (not to do list, mind you, there are plenty of those).

Having a personal archive of documents and notes sucks. Best effort used to be Evernote and MS one note. Proprietary plateform and standards, lock ins and of course they access your stuff.

Noting stuff on the way is hacking. I use telegram self-messaging for that because it let me quickly write, film, record stuff and queue them in a thread that sync accross my devices.

And contacts are still a mess. Once in a while, you receive the "I changed my phone/lost my contacts/new email/made a mistake" text asking "who is this ?". I still note metadata in the "name" field of contact to remember where I know the person from, or the name of their children to avoid being awkward when meeting them again.

Still we have an amazing free map of the entire world, more quality video content we can ever consume and encyclopedic knowledge of my entire field of expertise at my fingertip.

The way computer evolved is weird.

"Still we have an amazing free map of the entire world, more quality video content we can ever consume and encyclopedic knowledge of my entire field of expertise at my fingertip.

The way computer evolved is weird. "

To some extent, that's understandable. Storing and accessing static objective information that is the same for every user, that's easy, in a way it's just a matter of bandwidth and storage space.

Personal information and personal workflows, that is a different matter entirely.

Is it even legal to upload contacts under GDPR?

Well, the GDPR doesn't apply to "a natural person in the course of a purely personal or household activity", so they can upload them, assuming they're personal contacts.

For contacts of clients and such, probably yes, since whatever conditions for allowing their processing in Gmail probably also apply to Skype (and vice-versa). But it might not if for some reason the other service offers less security or control over that data.

That makes sense from the uploader side. But can the service store and use data about me because you uploaded it? In this case I have only added my data to Gmail, and never allowed Skype to have it and have not accepted the terms from Skype.

Maybe. It can probably use this to help the user who uploaded it do something, since for that purpose it's evidently suitable - if I upload the claim that rypskar has the nickname "Dog boy", their phone number is +1-555-555-1234 but they live in New Zealand, then providing that information back to me seems pretty harmless even if it is bogus.

But if they take this data and then try to do something else with it, whether that's contact rypskar or give the data about rypskar to somebody else - that's going to run into lots of GDPR problems around correctness (the data processor is obliged to take reasonable steps to ensure the data is accurate and fix problems on request) and as you identified with permissions (did rypskar authorise this? How do we know? Who even is rypskar?)

Not but I certainly wish for a way to merge all the contacts from thunderbird, my 3 web mail services, my phone et have them offline on my laptop.

Really? I wanted to see who I knew when LinkedIn first came out. Likewise when FB was released. Likewise when Twitter came out.

Do you use any of those services? If so did you create your contact list from scratch on each?

None of my friends are on TikTok AFAICT but if they were I'd want to know.

> I wanted to see who I knew when LinkedIn first came out.

I'm curious, why? I sign up to different services (reluctantly) because I want to communicate with people I can't yet. Occasionally I might have some contacts on two networks, if there's some specific feature I want to use, but it's rare.

I wanted to stay in touch as they changed roles. I still do.

> Occasionally I might have some contacts on two networks, if there's some specific feature I want to use, but it's rare.

Are you sure you don't have business contacts who are also in your email address book?

> I wanted to stay in touch as they changed roles

Sure, I might want that with a few coworkers, but not with my brother, aunt, friend's boyfriend or mother, tenant who rents my house, the shop who delivers butane, etc. Essentially 95% of my contacts are not relevant to a specific network, and dumping them indiscriminately seems not just bad form, but time wasting for me and them as well.

> Are you sure you don't have business contacts who are also in your email address book?

Yes, but they are a small subset of both circles.

> but not with my brother, aunt, friend's boyfriend or mother, tenant who rents my house, the shop who delivers butane, etc.

Given that we are discussing LinkedIn, wouldn't you just not connect with them? Seems like a small cost for having to add that 5% of people manually.

There is no such thing as "just not connect with them". Once it gets an address, LI will hound you and them, trying to convince them to signup and connect (they even lost a lawsuit over this), and then they'll leak the contacts for every other criminal to abuse them.

Yeah, I'll manually add a few people to avoid imposing that on myself and others.

True. These days we get all these kind of recommendations. We are not aware but we are granting access to our resources from one service to other services.

OAuth2 isn't a standard protocol. A real standard protocol is one where you can build a library around it and then use that to communicate with anyone else who conforms to the standard. OAuth2 is more of a description of the various homegrown authentication methods different websites have tried to create. None of those websites want to reimplement their auth to conform to the standards, so they just add their auth to the standard. This is standards conforming to practice, not practice conforming to standards.

Can you imagine if the HTTPS standard had to have 100 different variations to connect to 100 different sites on the net, with no way to detect which one was in use, so that you had to have the variations hardcoded for every site you visit? Because that's where we are with OAuth.

Worse, some of the practices which are now RFCs are complete garbage. The grant type Resource Owner Password Credentials[1], for example, requires that the third party server ask the user for their username and password. This defeats the entire purpose of OAuth. Don't give me some crap about this being useful for first-party servers: there are way simpler and more secure ways to authenticate first party servers. OAuth is for authenticating users with third-party servers, and you should absolutely, unequivocally not be letting third party servers ask the user for their username and password. This normalizes putting your passwords for one site into another site for nontechnical, which is outright irresponsible and unethical.

Yet in the handful of times I've authenticated with OAuth as a third party, more than one of the first-party sites I was authenticating with used this method, putting the onus on me to correctly handle their usernames and passwords. The reasons are obvious: 1. Doing it the insecure way is easier because it allows sites to avoid implementing an SSO portal to handle their own passwords and grant initial access (which, incidentally, isn't included in the standard protocol at all AFAIK, despite being necessary to make it work) and 2. The IETF somehow thought it was a good idea to give this awful security practice an air of validity with an RFC.

The OAuth2 protocol standard is a tire fire which is unsalvageable at this point. We need a new standard that is actually a fully-specified standard, with a single, clear path from start to finish, including the initial use of passwords to obtain tokens, which serves the single purpose of allowing third party services to authenticate in a secure way.

[1] https://tools.ietf.org/html/rfc6749#section-1.3.3

FYI, the IETF plans to deprecate the Resource Owner Password Credentials Grant you are talking about [1].

[1] https://tools.ietf.org/html/draft-ietf-oauth-security-topics

Okay, but why was this ever put into a standards track in the first place? This isn't an obscure error, it's the kind of glaring error that shows that a security standard is being designed by people who know next-to-nothing about security. Recently, when I implemented authentication to a site that used Resource Owner Password Credentials, my client's CTO reported it as a bug because he (correctly) noticed the security flaw. If you're making this sort of error, you have no business writing production authentication code, let alone standards for production authentication code.

And this is only the most glaring error. Another example: there's no specification for how to generate tokens, and I've implemented OAuth for platforms that return tokens which look suspiciously like UUIDs. Not only are UUIDs explicitly recommended against as credentials by RFC4122[1] because people could reverse engineer your UUID generation, but collisions have occurred in practice[2] without any reverse engineering, meaning that a user could authenticate as another user without even hacking.

And to clear, I'm not a security auditor and I've never done a security audit of any OAuth implementations except my own. These are problems I discovered by treating other people's OAuth implementations as black boxes, all of them compliant to the so-called "standard". Security is hard, and with so little specified, I imagine the majority of OAuth implementations in the wild are actually not secure.

[1] https://tools.ietf.org/html/rfc4122#page-16

[2] https://en.wikipedia.org/wiki/Universally_unique_identifier#...


   The resource owner password credentials grant MUST NOT be used.  This
   grant type insecurely exposes the credentials of the resource owner
   to the client.  Even if the client is benign, this results in an
   increased attack surface (credentials can leak in more places than
   just the AS) and users are trained to enter their credentials in
   places other than the AS.

   Furthermore, adapting the resource owner password credentials grant
   to two-factor authentication, authentication with cryptographic
   credentials, and authentication processes that require multiple steps
   can be hard or impossible (WebCrypto, WebAuthn).

Would OpenID Connect not satisfy this requirement? It's an authentication wrapper of OAuth2

I've implemented 10+ OAuth integrations, so I feel qualified to speak on that topic. I haven't implemented any OpenID integrations except one that used a library, so I don't feel qualified to comment.

This is far from a complete guide to the OAuth 2 protocol. I would recommend anyone wanting to communicate with, or implement a OAuth 2 server, to use the official RFC's as a reference.

What I’ve never been able to get a clear answer to is: how do I troubleshoot an Oauth workflow? I set up all the Oauth stuff on my end just as the documentation says, and the Google server (for example) returns an error. Now what? They don’t let me see their logs. The error message isn’t descriptive enough to know what to change. Google isn’t running an open source server where I can just spin up an instance myself to try it. The documentation seems to be out of date, or otherwise doesn’t match what I’m seeing.

This is everything I hate about using remote APIs, squared. I’ve never been able to make even the simplest example work.

I was trying to use Oauth to log in to an internal SharePoint site with VBA, and I did get some example code to work after a lot of messing around, but then it mysteriously stopped working a week later,* so I gave up and went back to scripting a browser.

*possibly because some system administrator noticed abnormal traffic and blocked it

Are there similar posts like this for UI best practices for implementing OAuth 2.0 as an authorization server? I've been looking for guides on how best to display the scopes and client details to the user, but I've basically had to rely on other authorization servers themselves for inspiration (Google, Github, etc.).

Has anyone written a blog post about OAuth authorization server UI design?

If you like diagrams, I've found that @darutk on Medium has some really good explanations of Oauth2 and OpenID. Example: https://medium.com/@darutk/diagrams-of-all-the-openid-connec...

Such great content now hostage to that website, what a pity.

Also look at their nice django-oauth-server: https://github.com/authlete/django-oauth-server

My experience using OpenID + OAuth2 was fantastic. I'd recommend delegating the responsibility of authentication to a third party like Cognito, Auth0 or Okta.

They can be pricey at scale, but as long as you follow the protocol without cramming more functionality into authentication than belongs there, you can swap them out for a self hosted solution.

Im not sure there ever will be a complete complete oauth2 considering everyone who implement it have their own flavor of it.

Yeah this is far from complete. It doesn't even mention OAuth scopes or standard flows. A more appropriate title would be "A Beginner's intro to OAuth2". This is way better:


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact