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 92c3859908c7235389be5fd6c18a200b4897d4ee
parent a652e46d95a2220ead7e5d23ed0a60ea3e4832f7
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Sat, 28 Sep 2024 11:22:07 +0200

feat(api): verify auth Bearer

Diffstat:
Msrc/api/server.cjs | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 71 insertions(+), 31 deletions(-)

diff --git a/src/api/server.cjs b/src/api/server.cjs @@ -57,6 +57,7 @@ const paths = [ '/v1/auth/verify', '/v1/echo', '/v1/auth/requestMagicLink', + '/v1/auth/invalidateToken', '/v1/leaderboard/allHeats', '/v1/leaderboard/allAthletes', '/v1/leaderboard/newHeat', @@ -104,6 +105,20 @@ server.on('request', async (req, res) => { res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + // extact authorization token + const authHeader = req.headers.authorization + let token = undefined + try { + if (authHeader.startsWith("Bearer ")) { + token = authHeader.substring(7, authHeader.length) + console.log(' Bearer token', token); + } + } catch(error) { + console.warn("x Warning: No authorization bearer token in request header") + //serverError(res, new Error("No authorization bearer token in request header")); + //return + } + // cors pre-flight request uses options method if (req.method === 'OPTIONS') { res.end() @@ -116,43 +131,19 @@ server.on('request', async (req, res) => { break case '/v1/auth/verify': try { - const token = search_params.get('token'); - - // lookup token in the database - const users = await db.lookupToken(token); - if (users.length < 1) { - throw {message: "Token not found"} - } - - const user = users[0] - - console.log(" Token expires_at:", users[0].expires_at); - console.log(" Time now, lah:", new Date()); - - // check expiration date of token in the database - if (new Date(users[0].expires_at) < new Date()) { - throw new Error('Token expired.. tthink about yu saad live 😿') - } - - // verify token signature - const v = jwt.verify(token, jwt_secret); - await db.invalidateToken(token); - console.log(" Verified token", v); - - if (v.email === user.email) { - res.end(JSON.stringify({ - message: 'Uncle roger verified 🤝 fuuiiyooh!', - data: user, - })); - } else { - throw new Error("Token signature invalid") - } + token = search_params.get('token'); + let user = await verifyToken(req, token) + res.end(JSON.stringify({ + message: 'Uncle roger verified 🤝 fuuiiyooh!', + data: user, + })); } catch (error) { serverError(res, error); } break case '/v1/leaderboard/allHeats': try { + await verifyToken(req, token) const heats = await db.allHeats() res.end(JSON.stringify({ @@ -165,6 +156,7 @@ server.on('request', async (req, res) => { break case '/v1/leaderboard/allAthletes': try { + await verifyToken(req, token) const athletes = await db.allAthletes() res.end(JSON.stringify({ @@ -253,6 +245,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -279,6 +272,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -305,6 +299,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -335,6 +330,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -365,6 +361,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -396,6 +393,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -428,6 +426,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -458,6 +457,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -486,6 +486,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -511,6 +512,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -540,6 +542,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -566,6 +569,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -598,6 +602,7 @@ server.on('request', async (req, res) => { }).on('end', async () => { const b = Buffer.concat(body); try { + await verifyToken(req, token) if (b.length < 1) { throw new Error("Empty request body") } @@ -631,6 +636,41 @@ server.on('request', async (req, res) => { } }); +// returns user on success, throws error otherwise +async function verifyToken(req, token) { + if (!token){ + throw {message: "No token found in verifyToken"} + } else if (token.length === 0) { + throw {message: "Token empty in verifyToken"} + } + + // lookup token in the database + const users = await db.lookupToken(token); + if (users.length < 1) { + throw {message: "User not found in verifyToken"} + } + + const user = users[0] + + console.warn(" Token expires_at:", users[0].expires_at); + console.log(" Time now, lah:", new Date()); + + // check expiration date of token in the database + if (new Date(users[0].expires_at) < new Date()) { + throw new Error('Token expired.. tthink about yu saad live 😿') + } + + // verify token signature + const v = jwt.verify(token, jwt_secret); + //await db.invalidateToken(token); + console.log(" Verified token", v); + + if (v.email !== user.email) { + throw new Error("Token signature invalid") + } + return user +} + function notFound(res, path) { console.error('x Error: 404 not found'); res.statusCode = 404;