Created
November 18, 2021 21:04
-
-
Save kentcdodds/5359ab59bf563347c9451ae04cf24a7e to your computer and use it in GitHub Desktop.
Authentication in Remix applications
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
import * as bcrypt from "bcrypt"; | |
import { createCookieSessionStorage, redirect } from "remix"; | |
import { db } from "./db.server"; | |
export type LoginForm = { | |
username: string; | |
password: string; | |
}; | |
export async function register({ username, password }: LoginForm) { | |
let passwordHash = await bcrypt.hash(password, 10); | |
return db.user.create({ | |
data: { username, passwordHash }, | |
}); | |
} | |
export async function login({ username, password }: LoginForm) { | |
const user = await db.user.findUnique({ where: { username } }); | |
if (!user) return null; | |
const isCorrectPassword = await bcrypt.compare(password, user.passwordHash); | |
if (!isCorrectPassword) return null; | |
return user; | |
} | |
let sessionSecret = process.env.SESSION_SECRET; | |
if (!sessionSecret) { | |
throw new Error("SESSION_SECRET must be set"); | |
} | |
let { getSession, commitSession, destroySession } = createCookieSessionStorage({ | |
cookie: { | |
name: "RJ_session", | |
secure: true, | |
secrets: [sessionSecret], | |
sameSite: "lax", | |
path: "/", | |
maxAge: 60 * 60 * 24 * 30, | |
httpOnly: true, | |
}, | |
}); | |
export function getUserSession(request: Request) { | |
return getSession(request.headers.get("Cookie")); | |
} | |
export async function getUserId(request: Request) { | |
let session = await getUserSession(request); | |
let userId = session.get("userId"); | |
if (!userId || typeof userId !== "string") return null; | |
return userId; | |
} | |
export async function requireUserId(request: Request) { | |
let session = await getUserSession(request); | |
let userId = session.get("userId"); | |
if (!userId || typeof userId !== "string") throw redirect("/login"); | |
return userId; | |
} | |
export async function getUser(request: Request) { | |
let session = await getUserSession(request); | |
let userId = session.get("userId"); | |
if (typeof userId !== "string") return null; | |
return db.user | |
.findUnique({ where: { id: userId } }) | |
.catch(() => Promise.reject(logout(request))); | |
} | |
export async function requireUser(request: Request) { | |
let session = await getUserSession(request); | |
let userId = session.get("userId"); | |
if (!session.has("userId")) throw redirect("/login"); | |
return db.user | |
.findUnique({ where: { id: userId } }) | |
.catch(() => Promise.reject(logout(request))); | |
} | |
export async function logout(request: Request) { | |
let session = await getSession(request.headers.get("Cookie")); | |
return redirect("/login", { | |
headers: { "Set-Cookie": await destroySession(session) }, | |
}); | |
} | |
export async function createUserSession(userId: string, redirectTo: string) { | |
let session = await getSession(); | |
session.set("userId", userId); | |
return redirect(redirectTo, { | |
headers: { "Set-Cookie": await commitSession(session) }, | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment