Supporting multiple auth providers
This is more so a high level backend question, but I am wondering what is the expected behavior if I want to allow users to sign in to my app via Google, Discord, GitHub, and even just plain ole credentials (email + password).
Should I create a separate account for each provider that the user logs in with (regardless of the email), or should I do some sort of auto account linking where I would merge multiple providers into the same account if the email is the same? Unsure if that would impose account hijacking issue or any other security issues.
Another potential edge case is that if I were to do account linking, say with Google and credentials, and the user changes their Google email, should I still honor the linkings because it's still the same Google account?
These are just some of the thoughts I had, so basically I am wondering if there's a standard way to handle supporting multiple auth providers.
20 Replies
This can get pretty complicated - a lot of people just do it by email and handle the edge cases manually via support tickets
could you explain more what you mean by email? Like as in linking multiple providers to an account by email (which is what i mentioned above)?
Yes, simply storing the email and in your auth flow just treating it like an email, password login but instead of verifying with a password you are trusting the providers response
Gotcha ty, that makes sense to me
Np
Also one more thing, I may also want to allow users to manually link their account to another provider, which doesn't necessarily need to have the same email.
How do you think I should handle this? I am considering making a "providers" DB table that is linked to "users" DB table by user ID. An user can have multiple providers basically (one to many relationship)
Yes, this is how I implemented a similar system
From my understanding linking multiple oauth providers would be a separate “flow” from a signup/signin. since there’s no way of knowing the account to link to unless you are already authenticated as a user
Right yep, after a complete authorization flow in the frontend, I would make an API call to my backend, which is where I would handle account linking
I am thinking of sending the corresponding token from the oauth provider to the backend so that I can verify it first. For example, if it's Google, I believe the id token is what you can use to verify and extract the user info
Yes - you definitely have to do it this way, otherwise it can be insecure. Have you tried using Next Auth - it handles most of this for you?
I think if they happen to login with a different provider, but it is with an existing email address you could link it then. More complicated if they are completely separate emails from different providers though
Yep I am using NextAuth! in the
signIn
callback, this is where I can retrieve the corresponding token and make the API call
Technically, in this entire flow, the processing would happen twice (both in NextAuth and then in my external backend), but I can't help that I don't think. Better to be secure than not
I think if they happen to login with a different provider, but it is with an existing email address you could link it thenYeah from the above discussion, that is what Jon also suggested to do, so I'll do that.
More complicated if they are completely separate emails from different providers thoughIn this case, I'll likely just make a new account if they are attempting to sign in/up with it
Except idk if this is correct or secure
I guess it is secure as long as there’s an email verification step if you’re going purely based off the email address? Idk I’m not an expert on this haha
Yeah I'll go purely based off the email address, and you're absolutely right that it could be insecure to completely trust it.
However, to my understanding, some providers (not all!) do either require that users must verify their email first or they provide a boolean flag that tells me if the email is verified or not.
If it's not verified, I'll cancel the flow and result in some error
Yeah
Oh I almost forgot. Maybe you’ve already seen this, but if you haven’t it could be helpful. https://v2.lucia-auth.com/guidebook/oauth-account-linking/
The v2 docs had a small page on this so maybe you can learn from the general process they’re saying. I couldn’t find anything on it in their v3 docs but good resource anyway
https://v3.lucia-auth.com/
Lucia v3
Lucia v3 documentation
Lucia is an open source auth library that abstracts away the complexity of handling sessions.
Ty, I'll take a look!
Yeah in the v2 link, that is essentially what I think I'll do
If the user with email exists, link the provider to it and return the user. Otherwise, make a new user and link the provider to it, return new user
After verification of course
And Lucia is all on GitHub so you should be able to see exactly how they write it. Good luck hope it works out!
Hey, if you've implemented manual account linking through Next Auth, I'm curious how you differentiate between a regular sign in and an account linking?
I was thinking maybe pass in an additional parameter to the
signIn
function, with something like {isAccountLink: true}
. This supposedly would set it as query param, which I could parse in the sign in callback.
Haven't tried it yet, but I'm curious if you went with better or different approach?
I saw another approach where you would check if there's currently a session, and then you can assume that the user is trying to manually link another provider
EDIT: I'll probably do this approach