From 09b9a5e8577c59f08757aefac1e9ec4c756d933b Mon Sep 17 00:00:00 2001 From: dswbx Date: Sat, 6 Dec 2025 20:51:09 +0100 Subject: [PATCH] fix(auth): `allow_register` was not respected in strategy controllers --- app/src/auth/api/AuthController.ts | 11 ++- .../strategies/PasswordStrategy.ts | 68 ++++++++++--------- .../auth/authenticate/strategies/Strategy.ts | 2 +- .../strategies/oauth/OAuthStrategy.ts | 6 +- 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/app/src/auth/api/AuthController.ts b/app/src/auth/api/AuthController.ts index af846ce..5345078 100644 --- a/app/src/auth/api/AuthController.ts +++ b/app/src/auth/api/AuthController.ts @@ -199,7 +199,12 @@ export class AuthController extends Controller { for (const [name, strategy] of Object.entries(strategies)) { if (!this.auth.isStrategyEnabled(strategy)) continue; - hono.route(`/${name}`, strategy.getController(this.auth.authenticator)); + hono.route( + `/${name}`, + strategy.getController(this.auth.authenticator, { + allow_register: this.auth.config.allow_register, + }), + ); this.registerStrategyActions(strategy, hono); } @@ -305,7 +310,9 @@ export class AuthController extends Controller { await c.context.ctx().helper.granted(c, AuthPermissions.testPassword); const pw = this.auth.authenticator.strategy("password") as PasswordStrategy; - const controller = pw.getController(this.auth.authenticator); + const controller = pw.getController(this.auth.authenticator, { + allow_register: this.auth.config.allow_register, + }); const res = await controller.request( new Request("https://localhost/login", { diff --git a/app/src/auth/authenticate/strategies/PasswordStrategy.ts b/app/src/auth/authenticate/strategies/PasswordStrategy.ts index 7f2c964..b8a48b0 100644 --- a/app/src/auth/authenticate/strategies/PasswordStrategy.ts +++ b/app/src/auth/authenticate/strategies/PasswordStrategy.ts @@ -87,7 +87,7 @@ export class PasswordStrategy extends AuthStrategy { }; } - getController(authenticator: Authenticator): Hono { + getController(authenticator: Authenticator, opts: { allow_register?: boolean }): Hono { const hono = new Hono(); const redirectQuerySchema = s.object({ redirect: s.string().optional(), @@ -120,41 +120,43 @@ export class PasswordStrategy extends AuthStrategy { }, ); - hono.post( - "/register", - describeRoute({ - summary: "Register a new user with email and password", - tags: ["auth"], - }), - jsc("query", redirectQuerySchema), - async (c) => { - try { - const { redirect } = c.req.valid("query"); - const { password, email, ...body } = parse( - payloadSchema, - await authenticator.getBody(c), - { - onError: (errors) => { - $console.error("Invalid register payload", [...errors]); - new InvalidCredentialsException(); + if (opts.allow_register) { + hono.post( + "/register", + describeRoute({ + summary: "Register a new user with email and password", + tags: ["auth"], + }), + jsc("query", redirectQuerySchema), + async (c) => { + try { + const { redirect } = c.req.valid("query"); + const { password, email, ...body } = parse( + payloadSchema, + await authenticator.getBody(c), + { + onError: (errors) => { + $console.error("Invalid register payload", [...errors]); + new InvalidCredentialsException(); + }, }, - }, - ); + ); - const profile = { - ...body, - email, - strategy_value: await this.hash(password), - }; + const profile = { + ...body, + email, + strategy_value: await this.hash(password), + }; - return await authenticator.resolveRegister(c, this, profile, async () => void 0, { - redirect, - }); - } catch (e) { - return authenticator.respondWithError(c, e as any); - } - }, - ); + return await authenticator.resolveRegister(c, this, profile, async () => void 0, { + redirect, + }); + } catch (e) { + return authenticator.respondWithError(c, e as any); + } + }, + ); + } return hono; } diff --git a/app/src/auth/authenticate/strategies/Strategy.ts b/app/src/auth/authenticate/strategies/Strategy.ts index bb72d85..190ea61 100644 --- a/app/src/auth/authenticate/strategies/Strategy.ts +++ b/app/src/auth/authenticate/strategies/Strategy.ts @@ -36,7 +36,7 @@ export abstract class AuthStrategy { protected abstract getSchema(): Schema; - abstract getController(auth: Authenticator): Hono; + abstract getController(auth: Authenticator, opts: { allow_register?: boolean }): Hono; getType(): string { return this.type; diff --git a/app/src/auth/authenticate/strategies/oauth/OAuthStrategy.ts b/app/src/auth/authenticate/strategies/oauth/OAuthStrategy.ts index 641c9b7..89fb60a 100644 --- a/app/src/auth/authenticate/strategies/oauth/OAuthStrategy.ts +++ b/app/src/auth/authenticate/strategies/oauth/OAuthStrategy.ts @@ -284,7 +284,7 @@ export class OAuthStrategy extends AuthStrategy { } } - getController(auth: Authenticator): Hono { + getController(auth: Authenticator, opts: { allow_register?: boolean }): Hono { const hono = new Hono(); const secret = "secret"; const cookie_name = "_challenge"; @@ -379,6 +379,10 @@ export class OAuthStrategy extends AuthStrategy { return c.notFound(); } + if (action === "register" && !opts.allow_register) { + return c.notFound(); + } + const url = new URL(c.req.url); const path = url.pathname.replace(`/${action}`, ""); const redirect_uri = url.origin + path + "/callback";