myheats

Live heats, scoring and leaderboard for sport events
git clone https://git.in0rdr.ch/myheats.git
Log | Files | Refs | Pull requests | README | LICENSE

commit 460fadf96f8827ea3a5fb9bf95e0599feff4ab90
parent 473b1566e4c4c8036d34ebb2afbf1c2e34986525
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Mon, 16 Sep 2024 00:13:42 +0200

feat(magic): distinct jwt/session ttl

Diffstat:
M.env | 24+++++++++++++++++-------
Msrc/Auth.jsx | 5+++--
Msrc/AuthVerify.jsx | 9++++-----
Msrc/api/server.cjs | 23++++++++++-------------
4 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/.env b/.env @@ -1,3 +1,7 @@ +############ +# Frontend # +############ + # Anonymous public API key for the Supabase project # https://app.supabase.com/project/_/settings/api VITE_APP_SUPABASE_KEY= @@ -5,17 +9,23 @@ VITE_APP_SUPABASE_KEY= VITE_APP_SUPABASE_URL= # Application window title VITE_APP_DOC_TITLE='My Heats' - +# Cookie TTL in seconds (session ttl in the admin/judges frontend), 60m +VITE_SESSION_TTL=3600 # Full URI to backend API -MYHEATS_API=http://127.0.0.1 +VITE_API_URI=http://127.0.0.1 # Backend API port -MYHEATS_API_PORT=8000 -# Redirect address, MyHeats frontend URL -MYHEATS_REDIRECT_URI=http://localhost:5173/authverify +VITE_API_PORT=8000 + +########### +# Backend # +########### +API_REDIRECT_URI=http://localhost:5173/authverify # Backend API CORS allowed origins -MYHEATS_API_CORS_ALLOW_ORIGIN=http://localhost:5173 +API_CORS_ALLOW_ORIGIN=http://localhost:5173 # JWT secret for magic links (`openssl rand -base64 48`) -MYHEATS_API_JWT_SECRET= +API_JWT_SECRET= +# JWT TTL in seconds (validity of the magic link), 5m +API_JWT_TTL=300 # SMTP settings for sending magic links SMTP_HOST= diff --git a/src/Auth.jsx b/src/Auth.jsx @@ -1,7 +1,8 @@ import { useState } from 'react' -const api_uri = import.meta.env.MYHEATS_API ? import.meta.env.MYHEATS_API: 'http://127.0.0.1' -const api_port = import.meta.env.MYHEATS_API_PORT ? import.meta.env.MYHEATS_API_PORT: '8000' +const session_ttl = import.meta.env.VITE_SESSION_TTL ? import.meta.env.VITE_SESSION_TTL : '3600' +const api_uri = import.meta.env.VITE_API_URI ? import.meta.env.VITE_API_URI: 'http://127.0.0.1' +const api_port = import.meta.env.VITE_API_PORT ? import.meta.env.VITE_API_PORT: '8000' function Auth() { const [loading, setLoading] = useState(false) diff --git a/src/AuthVerify.jsx b/src/AuthVerify.jsx @@ -1,8 +1,9 @@ import { useState, useEffect } from 'react' import { CookiesProvider, useCookies } from 'react-cookie' -const api_uri = import.meta.env.MYHEATS_API ? import.meta.env.MYHEATS_API: 'http://127.0.0.1' -const api_port = import.meta.env.MYHEATS_API_PORT ? import.meta.env.MYHEATS_API_PORT: '8000' +const api_uri = import.meta.env.VITE_API_URI +const api_port = import.meta.env.VITE_API_PORT +const session_ttl = import.meta.env.VITE_SESSION_TTL function AuthVerify() { const [loading, setLoading] = useState(true) @@ -17,7 +18,6 @@ function AuthVerify() { const response = await fetch(`${api_uri}:${api_port}/v1/auth/verify?token=${token}`) const { message, data, error } = await response.json() setResponse(data) - console.log("Uncle roger be like:", message) if (error) { alert(error) @@ -26,8 +26,7 @@ function AuthVerify() { setSession('auth', data, { path: '/', secure: process.env.NODE_ENV !== 'development', - // todo: reuses Token expiration, this could be different - expires: new Date(data.expires_at), + maxAge: parseInt(session_ttl), }) // redirect if everything ok diff --git a/src/api/server.cjs b/src/api/server.cjs @@ -18,18 +18,15 @@ require('dotenv').config({ }); // Read environment and set defaults -api_uri = process.env.MYHEATS_API; -api_port = process.env.MYHEATS_API_PORT; -redirect_uri = process.env.MYHEATS_REDIRECT_URI; -cors_allow_origin = process.env.MYHEATS_API_CORS_ALLOW_ORIGIN; -jwt_secret = process.env.MYHEATS_API_JWT_SECRET; -cors_allow_origin = (cors_allow_origin === undefined) ? "*" : cors_allow_origin; -api_uri = (api_uri === undefined) ? 'http://127.0.0.1' : api_uri; -api_port = (api_port === undefined) ? 8000 : api_port; -redirect_uri= (redirect_uri === undefined) ? "http://localhost:5173" : redirect_uri +api_uri = process.env.VITE_API_URI; +api_port = process.env.VITE_API_PORT; +redirect_uri = process.env.API_REDIRECT_URI; +cors_allow_origin = process.env.API_CORS_ALLOW_ORIGIN; +jwt_secret = process.env.API_JWT_SECRET; +jwt_ttl = process.env.API_JWT_TTL; if (jwt_secret === undefined) { - console.log('Balls, MYHEATS_API_JWT_SECRET undefined 🍳'); + console.log('Balls, API_JWT_SECRET undefined 🍳'); process.exit() } else if (process.env.SMTP_HOST === undefined || process.env.SMTP_PORT === undefined || @@ -156,10 +153,10 @@ const server = http.createServer(async (req, res) => { const user = users[0] - // create magic link valid for 5m (300s) - const exp = new Date(Date.now() + 300000) + // create magic link + const exp = new Date(Date.now() + 1000 * jwt_ttl) const token = jwt.sign({ email: user.email }, jwt_secret, { - expiresIn: 300, + expiresIn: 1000 * jwt_ttl, }) const magic_link = `${redirect_uri}?token=${token}` const magic_href = `${api_uri}:${api_port}/v1/auth/verify?token=${token}`