From 5e2d23f18f4e35d38bc6460b9aff67aaf6e18478 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 11 Oct 2022 21:48:33 -0700 Subject: [PATCH] Refactor auth logic. --- components/metrics/WebsiteHeader.js | 8 ++++---- components/pages/TestConsole.js | 2 +- components/settings/WebsiteSettings.js | 2 +- lib/auth.js | 20 +++++++++++--------- lib/middleware.js | 5 +++-- lib/session.js | 2 +- package.json | 2 +- pages/api/share/[id].js | 6 +++--- pages/api/websites/[id]/index.js | 9 +++++---- yarn.lock | 14 ++++++++++---- 10 files changed, 40 insertions(+), 30 deletions(-) diff --git a/components/metrics/WebsiteHeader.js b/components/metrics/WebsiteHeader.js index 15f6d0ff..1a6bdf15 100644 --- a/components/metrics/WebsiteHeader.js +++ b/components/metrics/WebsiteHeader.js @@ -17,8 +17,8 @@ export default function WebsiteHeader({ websiteId, title, domain, showLink = fal {title} @@ -41,8 +41,8 @@ export default function WebsiteHeader({ websiteId, title, domain, showLink = fal {showLink && ( } size="small" diff --git a/components/pages/TestConsole.js b/components/pages/TestConsole.js index c1e59b1b..215c350c 100644 --- a/components/pages/TestConsole.js +++ b/components/pages/TestConsole.js @@ -55,7 +55,7 @@ export default function TestConsole() {
Test Console
diff --git a/components/settings/WebsiteSettings.js b/components/settings/WebsiteSettings.js index 7e9371f5..f044bd68 100644 --- a/components/settings/WebsiteSettings.js +++ b/components/settings/WebsiteSettings.js @@ -84,7 +84,7 @@ export default function WebsiteSettings() { ); const DetailsLink = ({ id, name, domain }) => ( - + {name} diff --git a/lib/auth.js b/lib/auth.js index fa1cfec2..c84f22e8 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -1,10 +1,10 @@ import { validate } from 'uuid'; -import { parseSecureToken, parseToken, getItem } from 'next-basics'; -import { AUTH_TOKEN, SHARE_TOKEN_HEADER } from './constants'; +import { parseSecureToken, parseToken } from 'next-basics'; import { getWebsite } from 'queries'; -import { secret } from './crypto'; +import { SHARE_TOKEN_HEADER } from 'lib/constants'; +import { secret } from 'lib/crypto'; -export async function getAuthToken(req) { +export function getAuthToken(req) { try { const token = req.headers.authorization; @@ -14,13 +14,15 @@ export async function getAuthToken(req) { } } -export function getAuthHeader() { - const token = getItem(AUTH_TOKEN); - - return token ? { authorization: `Bearer ${token}` } : {}; +export function getShareToken(req) { + try { + return parseSecureToken(req.headers[SHARE_TOKEN_HEADER], secret()); + } catch { + return null; + } } -export async function isValidToken(token, validation) { +export function isValidToken(token, validation) { try { const result = parseToken(token, secret()); diff --git a/lib/middleware.js b/lib/middleware.js index f7289335..753814b0 100644 --- a/lib/middleware.js +++ b/lib/middleware.js @@ -1,7 +1,7 @@ import { createMiddleware, unauthorized, badRequest, serverError } from 'next-basics'; import cors from 'cors'; import { getSession } from './session'; -import { getAuthToken } from './auth'; +import { getAuthToken, getShareToken } from './auth'; export const useCors = createMiddleware(cors()); @@ -27,11 +27,12 @@ export const useSession = createMiddleware(async (req, res, next) => { export const useAuth = createMiddleware(async (req, res, next) => { const token = await getAuthToken(req); + const shareToken = await getShareToken(req); if (!token) { return unauthorized(res); } - req.auth = token; + req.auth = { ...token, shareToken }; next(); }); diff --git a/lib/session.js b/lib/session.js index 487c1c6a..488d9c52 100644 --- a/lib/session.js +++ b/lib/session.js @@ -31,7 +31,7 @@ export async function getSession(req) { let websiteId = null; - // Check if websites exists + // Check if website exists if (redis.enabled) { websiteId = Number(await redis.get(`website:${websiteUuid}`)); } diff --git a/package.json b/package.json index edec73e7..48d74bf5 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "maxmind": "^4.3.6", "moment-timezone": "^0.5.35", "next": "^12.2.5", - "next-basics": "^0.12.0", + "next-basics": "^0.17.0", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "prop-types": "^15.7.2", diff --git a/pages/api/share/[id].js b/pages/api/share/[id].js index c0521235..620967c7 100644 --- a/pages/api/share/[id].js +++ b/pages/api/share/[id].js @@ -9,10 +9,10 @@ export default async (req, res) => { const website = await getWebsiteByShareId(id); if (website) { - const websiteId = website.websiteId; - const token = createToken({ websiteId: websiteId }, secret()); + const { websiteId, websiteUuid } = website; + const token = createToken({ websiteId, websiteUuid }, secret()); - return ok(res, { websiteId, token }); + return ok(res, { websiteId, websiteUuid, token }); } return notFound(res); diff --git a/pages/api/websites/[id]/index.js b/pages/api/websites/[id]/index.js index c6b8779f..9b8af2e4 100644 --- a/pages/api/websites/[id]/index.js +++ b/pages/api/websites/[id]/index.js @@ -5,6 +5,10 @@ import { useAuth, useCors } from 'lib/middleware'; import { validate } from 'uuid'; export default async (req, res) => { + await useAuth(req, res); + + const { isAdmin, userId, accountUuid } = req.auth; + const { id } = req.query; const websiteId = +id; @@ -23,9 +27,6 @@ export default async (req, res) => { } if (req.method === 'POST') { - await useAuth(req, res); - - const { isAdmin: currentUserIsAdmin, userId: currentUserId, accountUuid } = req.auth; const { name, domain, owner, enable_share_url } = req.body; let account; @@ -37,7 +38,7 @@ export default async (req, res) => { const shareId = enable_share_url ? website.shareId || getRandomChars(8) : null; - if (website.userId !== currentUserId && !currentUserIsAdmin) { + if (website.userId !== userId && !isAdmin) { return unauthorized(res); } diff --git a/yarn.lock b/yarn.lock index 91c1e9d9..7f4f9c06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2273,6 +2273,11 @@ balanced-match@^2.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== +base-x@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" + integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -4731,11 +4736,12 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -next-basics@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.12.0.tgz#e946cdb3f32d5d84f67e7c35b6e2e96750763c62" - integrity sha512-3meED1Z9m8QvOsG4bz5OAuyjROdV9Cf75Wq2t+cHiGBh+y8qhTluJduqIXuoY5x0S72/5XvY1mwthW+Og47H9A== +next-basics@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.17.0.tgz#567c7b7a05f02bf6e4a073090954c1b6de4e7045" + integrity sha512-NXYfbdBCdbn/a6x4F+7zZGmJ8llHtZcUYp3BMwoYXRSPsa1Y4wmJgIgtGBu542IMfTkQ2YClBy3Z1gOoMbzgaQ== dependencies: + base-x "^4.0.0" bcryptjs "^2.4.3" jsonwebtoken "^8.5.1"