Created
August 3, 2023 02:46
-
-
Save kentcdodds/ccf85ad488251c6edc1de083f45ef652 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const sessionKey = 'sessionId' | |
export const authenticator = new Authenticator<string>(sessionStorage, { | |
sessionKey, | |
}) | |
authenticator.use( | |
new GitHubStrategy( | |
{ | |
clientID: process.env.GITHUB_CLIENT_ID, | |
clientSecret: process.env.GITHUB_CLIENT_SECRET, | |
callbackURL: '/auth/github/callback', | |
}, | |
async ({ profile, request }) => { | |
const email = profile.emails[0].value.trim().toLowerCase() | |
const id = profile.id | |
// Connection exists already? Make a new session | |
const existingConnection = await prisma.gitHubConnection.findUnique({ | |
select: { userId: true }, | |
where: { providerId: id }, | |
}) | |
if (existingConnection) { | |
const session = await prisma.session.create({ | |
select: { id: true, expirationDate: true, userId: true }, | |
data: { | |
expirationDate: new Date(Date.now() + SESSION_EXPIRATION_TIME), | |
userId: existingConnection.userId, | |
}, | |
}) | |
const verification = await prisma.verification.findUnique({ | |
select: { id: true }, | |
where: { | |
target_type: { | |
target: session.userId, | |
type: twoFAVerificationType, | |
}, | |
}, | |
}) | |
// has 2FA? redirect to verify | |
const userHasTwoFactor = Boolean(verification) | |
if (userHasTwoFactor) { | |
const verifySession = await verifySessionStorage.getSession( | |
request.headers.get('cookie'), | |
) | |
verifySession.set(unverifiedSessionIdKey, session.id) | |
const reqUrl = new URL(request.url) | |
const redirectUrl = getRedirectToUrl({ | |
request, | |
type: twoFAVerificationType, | |
target: session.userId, | |
redirectTo: reqUrl.searchParams.get('redirectTo') ?? '/', | |
}) | |
throw redirect(redirectUrl.toString(), { | |
headers: { | |
'set-cookie': await verifySessionStorage.commitSession( | |
verifySession, | |
), | |
}, | |
}) | |
} else { | |
return session.id | |
} | |
} | |
// If we're already logged in, then link the GitHub account | |
const userId = await getUserId(request) | |
if (userId) { | |
await prisma.gitHubConnection.create({ | |
data: { providerId: id, userId }, | |
}) | |
const session = await getSession(request.headers.get('cookie')) | |
return session.get(sessionKey) // Return the existing session | |
} | |
// if the github email matches a user in the db, then link the account and | |
// make a new session | |
const user = await prisma.user.findUnique({ | |
select: { id: true }, | |
where: { email }, | |
}) | |
if (user) { | |
await prisma.gitHubConnection.create({ | |
data: { providerId: id, userId: user.id }, | |
}) | |
const session = await prisma.session.create({ | |
select: { id: true }, | |
data: { | |
expirationDate: new Date(Date.now() + SESSION_EXPIRATION_TIME), | |
userId: user.id, | |
}, | |
}) | |
return session.id | |
} | |
// this is a new user, so let's get them onboarded | |
const verifySession = await verifySessionStorage.getSession( | |
request.headers.get('cookie'), | |
) | |
verifySession.set(onboardingEmailSessionKey, email) | |
throw redirect('/onboarding', { | |
headers: { | |
'Set-Cookie': await verifySessionStorage.commitSession(verifySession), | |
}, | |
}) | |
}, | |
), | |
GitHubStrategy.name, | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment