Add API endpoints at `/api/auth/link` and `/api/auth/unlink`
Closed this issue ยท 6 comments
Add API endpoints at /api/auth/link
and /api/auth/unlink
for linking and unlinking OAuth accounts. This was a feature of v1 but did not make the cut for v2.0.
Note:
The /api/auth/signin
endpoint currently lets you link accounts securely (i.e. if signed in and then you sign in with a different account).
Once a page at /api/auth/link
is implemented /api/auth/signin
should probably direct users there if the user is signed in. It would effectively be the same as the sign in page, but would only list OAuth providers, and would have 'Unlink' options for providers that are already linked.
Does this let users link social OAuth accounts that don't return an email address?
That's a great question!
So (unless there is an additional check somewhere I have missed) yes it does allow this, which was also the case with version 1. Like version 1, version 2 currently requires an email address to create a user account, but is limited in that it only stores one email address per user.
Once you have a user account, you can link as many accounts as you like (or unlink them all, which is safe because you can still always log in via email).
Not allowing people to unlink all accounts unless an email is specified is good example of an edge case that comes up if you don't require an email address.
There is probably a good discussion to be had around how multiple email addresses could be tracked per user.
e.g. Perhaps it could even use the existing account
database (e.g. with provider: 'email'
, type: 'email'
and the email address for the account ID), as it would already enforce uniqueness, but we'd probably want to add a 'verified' flag and also we'd want to consider what we do with the existing user object (would it then be used to store a primary email address?)
Cool, might be a good idea to add to the each OAuth provider's docs which one returns an email address and can be used for both signup and linking and which ones don't return an email address and can only be used for linking.
Curious what the status is of this issue?
Ideally I'd like the following experience:
- User can sign up with email, Google, Spotify or Soundcloud
- After signing in, prompt user to connect the rest of their music accounts, e.g. Google (Youtube), Spotify and Soundcloud
Is this still planned?
For anyone that wants to allow users to link an OAuth account to a user, but not register with one, try this advanced initialization (getUser
is just a function to retrieve the user from the database):
import type { NextApiRequest, NextApiResponse } from 'next'
import type { NextAuthOptions } from 'next-auth'
import NextAuth from 'next-auth'
import EmailProvider from 'next-auth/providers/email'
import GoogleProvider from 'next-auth/providers/google'
import { getSession } from 'next-auth/react'
export function getNextAuthOptions(req?: NextApiRequest): NextAuthOptions {
return {
providers: [
EmailProvider({ ... }),
GoogleProvider({ ... }),
],
callbacks: {
async signIn({ user, account }) {
if (account.provider === 'email') {
// Allow login by email if the User already exists
return Boolean(await getUser({ email: user.email }))
}
if (account.provider === 'google') {
// Allow connecting a Google account to an authenticated User
if (await getSession({ req })) {
return true
}
// Allow login by an already connected Google account
if (await getUser({ id: user.id })) {
return true
}
return false
}
return false
},
},
}
}
export default async function auth(req: NextApiRequest, res: NextApiResponse) {
return await NextAuth(req, res, getNextAuthOptions(req))
}
The use case for me here was that users can only register through an email invitation from another user, but should be able to connect their Google account once logged in.
The key was being able to access the user session from within the signIn
callback, which took me embarrassingly long to figure out how to do. So hopefully this helps someone save some time!