Last active
January 2, 2022 01:19
-
-
Save kauffmanes/131621c52778d62e74819f2812a098c6 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// FILE #1: app/utils/session.ts | |
import jwt from 'jsonwebtoken'; | |
import { redirect } from 'remix'; | |
export function requireValidSession(request: Request) { | |
// assuming key is stored as base64 | |
// if not, no need for this line, just use env var directly | |
const publicKey = Buffer.from(process.env.JWT_PUBLIC_KEY || '', 'base64').toString('ascii'); | |
const tokenName = process.env.USERFRONT_TOKEN_NAME || ''; | |
if (!tokenName) { | |
throw redirect('/login', 401); | |
} | |
const cookieObj = parseCookie(request.headers.get("Cookie")); | |
const accessToken = cookieObj.hasOwnProperty(tokenName) && cookieObj[tokenName] || null; | |
if (!accessToken || !publicKey) { | |
throw redirect('/login', 401); | |
} | |
try { | |
const verifiedPayload = jwt.verify(accessToken, publicKey, { algorithms: ['RS256'] }); | |
return verifiedPayload; | |
} catch(err) { | |
throw redirect('/login', 401); | |
} | |
} | |
// https://www.30secondsofcode.org/js/s/parse-cookie | |
function parseCookie(str: string | null) { | |
if (!str) return {}; | |
return str.split(';').map(v => v.split('=')) | |
.reduce((acc: any, v) => { | |
acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); | |
return acc; | |
}, {}); | |
} | |
// FILE #2: Protected Route | |
import { useLoaderData } from 'remix'; | |
import { requireValidSession } from "../../utils/session"; | |
export async function loader({ request }: { request: Request }) { | |
export async function loader({ request }: { request: Request }) { | |
return requireValidSession(request); | |
} | |
export default function Dashboard() { | |
const userData = useLoaderData(); | |
return ( | |
<div> | |
Welcome to the Dashboard! | |
{JSON.stringify(userData)} | |
</div> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I spent a few days trying to figure out how to use Userfront with Remix Run. Caveat to this code: it works but I'm not confident it's the most secure or best way to do this. I think I would have preferred to use Remix built-in functions but I couldn't get it working. If you have a better way of doing it, please post!