From 8d5f7797cb371703f4075c0b2aabbb95f7a92618 Mon Sep 17 00:00:00 2001 From: Jordan Dalby Date: Mon, 25 Nov 2024 12:07:37 +0000 Subject: [PATCH] Optionally disable standard login --- README.md | 2 + client/src/components/auth/LoginPage.tsx | 124 +++++++------- client/src/components/auth/RegisterPage.tsx | 170 +++++++++++--------- client/src/types/user.ts | 1 + docker-compose.yaml | 2 + server/src/middleware/auth.js | 2 + server/src/routes/authRoutes.js | 15 +- 7 files changed, 180 insertions(+), 136 deletions(-) diff --git a/README.md b/README.md index b4996fb..711b933 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ services: TOKEN_EXPIRY: 24h ALLOW_NEW_ACCOUNTS: "true" DEBUG: "true" + DISABLE_ACCOUNTS: "false" + DISABLE_INTERNAL_ACCOUNTS: "false" # See https://github.com/jordan-dalby/ByteStash/wiki/Single-Sign%E2%80%90on-Setup for more info OIDC_ENABLED: "false" diff --git a/client/src/components/auth/LoginPage.tsx b/client/src/components/auth/LoginPage.tsx index 35cf317..7c85fdb 100644 --- a/client/src/components/auth/LoginPage.tsx +++ b/client/src/components/auth/LoginPage.tsx @@ -66,6 +66,8 @@ export const LoginPage: React.FC = () => { window.location.href = `${window.__BASE_PATH__}/api/auth/oidc/auth`; }; + const showInternalRegistration = !authConfig?.disableInternalAccounts; + return (
@@ -75,7 +77,7 @@ export const LoginPage: React.FC = () => {

Please sign in to continue - {authConfig?.allowNewAccounts ? ( + {authConfig?.allowNewAccounts && showInternalRegistration ? ( <> , create an{' '} @@ -101,72 +103,76 @@ export const LoginPage: React.FC = () => { > Sign in with {oidcConfig.displayName} -

-
-
-
-
- - Or continue with password - + {showInternalRegistration && ( +
+
+
+
+
+ + Or continue with password + +
-
+ )} )} -
-
-
- setUsername(e.target.value)} - disabled={isLoading} - /> + {showInternalRegistration && ( + +
+
+ setUsername(e.target.value)} + disabled={isLoading} + /> +
+
+ setPassword(e.target.value)} + disabled={isLoading} + /> +
+
- setPassword(e.target.value)} +
-
- -
- -
- + + )}
); diff --git a/client/src/components/auth/RegisterPage.tsx b/client/src/components/auth/RegisterPage.tsx index 5878360..24f16ae 100644 --- a/client/src/components/auth/RegisterPage.tsx +++ b/client/src/components/auth/RegisterPage.tsx @@ -91,6 +91,8 @@ export const RegisterPage: React.FC = () => { window.location.href = `${window.__BASE_PATH__}/api/auth/oidc/auth`; }; + const showInternalRegistration = !authConfig?.disableInternalAccounts; + return (
@@ -137,91 +139,111 @@ export const RegisterPage: React.FC = () => { > Sign in with {oidcConfig.displayName} -
-
-
-
-
- - Or continue with password - + {showInternalRegistration && ( +
+
+
+
+
+ + Or continue with password + +
-
+ )} )} -
-
-
- - setUsername(e.target.value)} - disabled={isLoading} - /> -
-
- - setPassword(e.target.value)} - disabled={isLoading} - /> + {showInternalRegistration && ( + +
+
+ + setUsername(e.target.value)} + disabled={isLoading} + /> +
+
+ + setPassword(e.target.value)} + disabled={isLoading} + /> +
+
+ + setConfirmPassword(e.target.value)} + disabled={isLoading} + /> +
+
- - setConfirmPassword(e.target.value)} +
-
+ + )} -
- + Browse public snippets +
- + )}
); diff --git a/client/src/types/user.ts b/client/src/types/user.ts index efc4903..cdfdaf2 100644 --- a/client/src/types/user.ts +++ b/client/src/types/user.ts @@ -15,4 +15,5 @@ export interface AuthConfig { allowNewAccounts: boolean; hasUsers: boolean; disableAccounts: boolean; + disableInternalAccounts: boolean; } \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index ef1c3ca..d734617 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -19,6 +19,8 @@ services: - DEBUG=false # Should we use accounts at all? When enabled, it will be like starting a fresh account so export your snippets, no login required - DISABLE_ACCOUNTS=false + # Should internal accounts be disabled? + - DISABLE_INTERNAL_ACCOUNTS=false # Optional: Enable OIDC for Single Sign On - OIDC_ENABLED=true diff --git a/server/src/middleware/auth.js b/server/src/middleware/auth.js index f160e28..01dd323 100644 --- a/server/src/middleware/auth.js +++ b/server/src/middleware/auth.js @@ -20,6 +20,7 @@ const JWT_SECRET = getJwtSecret(); const ALLOW_NEW_ACCOUNTS = process.env.ALLOW_NEW_ACCOUNTS === 'true'; const TOKEN_EXPIRY = process.env.TOKEN_EXPIRY || '24h'; const DISABLE_ACCOUNTS = process.env.DISABLE_ACCOUNTS === 'true'; +const DISABLE_INTERNAL_ACCOUNTS = process.env.DISABLE_INTERNAL_ACCOUNTS === 'true'; function generateAnonymousUsername() { return `anon-${crypto.randomBytes(8).toString('hex')}`; @@ -74,5 +75,6 @@ export { TOKEN_EXPIRY, ALLOW_NEW_ACCOUNTS, DISABLE_ACCOUNTS, + DISABLE_INTERNAL_ACCOUNTS, getOrCreateAnonymousUser }; \ No newline at end of file diff --git a/server/src/routes/authRoutes.js b/server/src/routes/authRoutes.js index ef037dc..21998c7 100644 --- a/server/src/routes/authRoutes.js +++ b/server/src/routes/authRoutes.js @@ -1,6 +1,6 @@ import express from 'express'; import jwt from 'jsonwebtoken'; -import { JWT_SECRET, TOKEN_EXPIRY, ALLOW_NEW_ACCOUNTS, DISABLE_ACCOUNTS, getOrCreateAnonymousUser } from '../middleware/auth.js'; +import { JWT_SECRET, TOKEN_EXPIRY, ALLOW_NEW_ACCOUNTS, DISABLE_ACCOUNTS, DISABLE_INTERNAL_ACCOUNTS, getOrCreateAnonymousUser } from '../middleware/auth.js'; import userService from '../services/userService.js'; import { getDb } from '../config/database.js'; import { up_v1_5_0_snippets } from '../config/migrations/20241117-migration.js'; @@ -16,9 +16,10 @@ router.get('/config', async (req, res) => { res.json({ authRequired: true, - allowNewAccounts: (!hasUsers || ALLOW_NEW_ACCOUNTS) && !DISABLE_ACCOUNTS, + allowNewAccounts: !hasUsers || (ALLOW_NEW_ACCOUNTS && !DISABLE_ACCOUNTS), hasUsers, - disableAccounts: DISABLE_ACCOUNTS + disableAccounts: DISABLE_ACCOUNTS, + disableInternalAccounts: DISABLE_INTERNAL_ACCOUNTS }); } catch (error) { Logger.error('Error getting auth config:', error); @@ -28,6 +29,10 @@ router.get('/config', async (req, res) => { router.post('/register', async (req, res) => { try { + if (DISABLE_INTERNAL_ACCOUNTS) { + return res.status(403).json({ error: 'Internal account registration is disabled' }); + } + const db = getDb(); const userCount = db.prepare('SELECT COUNT(*) as count FROM users').get().count; const hasUsers = userCount > 0; @@ -66,6 +71,10 @@ router.post('/register', async (req, res) => { router.post('/login', async (req, res) => { try { + if (DISABLE_INTERNAL_ACCOUNTS) { + return res.status(403).json({ error: 'Internal accounts are disabled' }); + } + const { username, password } = req.body; const user = await userService.validateUser(username, password);