← Back to context

Comment by maxboone

13 hours ago

You should use the subject identifiers, not the usernames. You store a mapping of provider & subject to internal users yourself.

But this has been a problem in the past where people would hijack the email and create a new Google account to sign in with Google with.

Similarly, when someone deletes their account with a provider, someone else can re-register it and your hash will end up the same. The subject identifiers should be unique according to the spec.

Ah yeah but I wanted my platform to provide universal OAuth with any platform (that my app developer user trusts) as OAuth provider. If you rely entirely on subject identifiers; in theory, it gives one platform (OAuth provider) the ability to hijack any account belonging to users authenticating via a different platform; e.g. one platform could fake the subject identifiers of their own platform/provider to intentionally make them match that of target accounts from a different platform/provider.

Now, I realize that this would require a large-scale conspiracy by the company/platform to execute but I don't want to trust one platform with access to accounts coming from a different platform. I don't want any possible edge cases. I wanted to fully isolate them. If one platform was compromised; that would be bad news for a subset of users, but not all users.

If the maker of an application wants to trust some obscure platform as their OAuth provider; they're welcome to. In fact, I allow people running their own KeyCloak instances as provider to do their own OAuth so it's actually a realistic scenario.

This is why I used the hash approach; I have full control over the username on my platform.

[EDIT] I forgot to mention I incorporate the issuer's sub in addition to their username to produce a username with a hash which I use as my username. The key point I wanted to get across here is don't trust one provider with accounts created via a different provider.

  • Proprietary techniques like this are usually a good indication you’re missing something. In this case it sounds like you are missing appropriate validation of the issuer and/or token itself.

    • I want to support OAuth2, not OpenID so I don't rely on a JWT; I call the issuer's endpoint directly from my backend using their official domain name over HTTPS. I use the sub field to avoid re-allocation of usernames/emails but my point is that I don't trust it on its own; I couple it with the provider ID.

      To make it universal, I had to keep complexity minimal and focus on the most supported protocol which is plain OAuth2.