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
Jon
Jon5d ago
This can get pretty complicated - a lot of people just do it by email and handle the edge cases manually via support tickets
Betrayy
BetrayyOP5d ago
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)?
Jon
Jon5d ago
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
Betrayy
BetrayyOP5d ago
Gotcha ty, that makes sense to me
Jon
Jon5d ago
Np
Betrayy
BetrayyOP5d ago
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)
Jon
Jon5d ago
Yes, this is how I implemented a similar system
Emyno
Emyno5d ago
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
Betrayy
BetrayyOP5d ago
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
Jon
Jon5d ago
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?
Emyno
Emyno5d ago
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
Betrayy
BetrayyOP5d ago
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 then
Yeah 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 though
In this case, I'll likely just make a new account if they are attempting to sign in/up with it
Emyno
Emyno5d ago
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
Betrayy
BetrayyOP5d ago
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
Emyno
Emyno5d ago
Yeah
Emyno
Emyno5d ago
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/
Emyno
Emyno5d ago
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.
Betrayy
BetrayyOP5d ago
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
Emyno
Emyno5d ago
And Lucia is all on GitHub so you should be able to see exactly how they write it. Good luck hope it works out!
Betrayy
BetrayyOP2d ago
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

Did you find this page helpful?