Skip to content

Instantly share code, notes, and snippets.

@kentcdodds
Created August 3, 2023 02:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kentcdodds/ccf85ad488251c6edc1de083f45ef652 to your computer and use it in GitHub Desktop.
Save kentcdodds/ccf85ad488251c6edc1de083f45ef652 to your computer and use it in GitHub Desktop.
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