From 9f1e89b5929e1100a10ee2a188048a8372ac92f0 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Fri, 11 Oct 2024 17:03:33 +0200 Subject: [PATCH] refactor(config): :fire: Remove old oidc section in config --- api/api/auth/login/index.ts | 27 +++++++++- api/api/v1/instance/index.ts | 25 ++++++--- api/api/v2/instance/index.ts | 24 ++++++--- app.ts | 2 +- config/config.example.toml | 67 +++++++++++++---------- config/config.schema.json | 73 +------------------------- packages/config-manager/config.type.ts | 30 +---------- packages/database-interface/user.ts | 11 +++- plugins/openid/routes/sso/index.ts | 4 +- 9 files changed, 116 insertions(+), 147 deletions(-) diff --git a/api/api/auth/login/index.ts b/api/api/auth/login/index.ts index 83aecb14..d26360a7 100644 --- a/api/api/auth/login/index.ts +++ b/api/api/auth/login/index.ts @@ -110,7 +110,30 @@ const returnError = (context: Context, error: string, description: string) => { export default apiRoute((app) => app.openapi(route, async (context) => { - if (config.oidc.forced) { + const oidcConfig = config.plugins?.config?.["@versia/openid"] as + | { + forced: boolean; + providers: { + id: string; + name: string; + icon: string; + }[]; + keys: { + private: string; + public: string; + }; + } + | undefined; + + if (!oidcConfig) { + return returnError( + context, + "invalid_request", + "The OpenID Connect plugin is not enabled on this instance. Cannot process login request.", + ); + } + + if (oidcConfig?.forced) { return returnError( context, "invalid_request", @@ -156,7 +179,7 @@ export default apiRoute((app) => // Try and import the key const privateKey = await crypto.subtle.importKey( "pkcs8", - Buffer.from(config.oidc.keys?.private ?? "", "base64"), + Buffer.from(oidcConfig?.keys?.private ?? "", "base64"), "Ed25519", false, ["sign"], diff --git a/api/api/v1/instance/index.ts b/api/api/v1/instance/index.ts index dcc746c0..469e5af0 100644 --- a/api/api/v1/instance/index.ts +++ b/api/api/v1/instance/index.ts @@ -53,6 +53,17 @@ export default apiRoute((app) => const knownDomainsCount = await Instance.getCount(); + const oidcConfig = config.plugins?.config?.["@versia/openid"] as + | { + forced: boolean; + providers: { + id: string; + name: string; + icon: string; + }[]; + } + | undefined; + // TODO: fill in more values return context.json({ approval_required: false, @@ -94,13 +105,15 @@ export default apiRoute((app) => }, version: "4.3.0-alpha.3+glitch", versia_version: version, + // TODO: Put into plugin directly sso: { - forced: false, - providers: config.oidc.providers.map((p) => ({ - name: p.name, - icon: proxyUrl(p.icon) || undefined, - id: p.id, - })), + forced: oidcConfig?.forced ?? false, + providers: + oidcConfig?.providers.map((p) => ({ + name: p.name, + icon: proxyUrl(p.icon) || undefined, + id: p.id, + })) ?? [], }, contact_account: contactAccount?.toApi() || undefined, } satisfies Record & { diff --git a/api/api/v2/instance/index.ts b/api/api/v2/instance/index.ts index 8c6932ea..b781e38f 100644 --- a/api/api/v2/instance/index.ts +++ b/api/api/v2/instance/index.ts @@ -133,6 +133,17 @@ export default apiRoute((app) => 30 * 24 * 60 * 60 * 1000, ); + const oidcConfig = config.plugins?.config?.["@versia/openid"] as + | { + forced: boolean; + providers: { + id: string; + name: string; + icon: string; + }[]; + } + | undefined; + // TODO: fill in more values return context.json({ domain: new URL(config.http.base_url).hostname, @@ -216,12 +227,13 @@ export default apiRoute((app) => hint: "", })), sso: { - forced: false, - providers: config.oidc.providers.map((p) => ({ - name: p.name, - icon: proxyUrl(p.icon) ?? "", - id: p.id, - })), + forced: oidcConfig?.forced ?? false, + providers: + oidcConfig?.providers.map((p) => ({ + name: p.name, + icon: proxyUrl(p.icon) ?? "", + id: p.id, + })) ?? [], }, }); }), diff --git a/app.ts b/app.ts index 99548c57..0846f82d 100644 --- a/app.ts +++ b/app.ts @@ -121,7 +121,7 @@ export const appFactory = async () => { const plugins = await loader.loadPlugins( join(process.cwd(), "plugins"), - config.plugins?.autoload, + config.plugins?.autoload ?? true, config.plugins?.overrides.enabled, config.plugins?.overrides.disabled, ); diff --git a/config/config.example.toml b/config/config.example.toml index b1614bc6..682b773f 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -53,35 +53,6 @@ rules = [ "Don't post illegal content", ] -[oidc] -# Run Versia Server with this value missing to generate a new key -# [oidc.keys] -# public = "XXXX" -# private = "XXXX" - -# If enabled, Versia Server will require users to log in with an OAuth provider -forced = false - -# Allow registration with OAuth providers -# Overriden by the signups.registration setting -allow_registration = true - -# The provider MUST support OpenID Connect with .well-known discovery -# Most notably, GitHub does not support this -# Redirect URLs in your OAuth provider can be set to this: -# /oauth/sso//callback* -# The asterisk is important, as it allows for any query parameters to be passed -# Authentik for example uses regex so it can be set to (regex): -# /oauth/sso//callback.* -# [[oidc.providers]] -# name = "CPlusPatch ID" -# id = "cpluspatch-id" -# This MUST match the provider's issuer URI, including the trailing slash (or lack thereof) -# url = "https://id.cpluspatch.com/application/o/versia-testing/" -# client_id = "XXXX" -# client_secret = "XXXXX" -# icon = "https://cpluspatch.com/images/icons/logo.svg" - [http] # The full URL Versia Server will be reachable by (paths are not supported) base_url = "https://versia.localhost:9900" @@ -424,3 +395,41 @@ max_coeff = 1.0 # Applies before the global ratelimit changes # "/api/v1/accounts/:id/block" = { duration = 30, max = 60 } # "/api/v1/timelines/public" = { duration = 60, max = 200 } + +[plugins] +# Whether to automatically load all plugins in the plugins directory +autoload = true + +# Override for autoload +[plugins.overrides] +enabled = [] +disabled = [] + +[plugins.config."@versia/openid"] +# If enabled, Versia will require users to log in with an OAuth provider +forced = false + +# Allow registration with OAuth providers +# Overriden by the signups.registration setting +allow_registration = true + +# [plugins.config."@versia/openid".keys] +# Run Versia Server with those values missing to generate a new key +# public = "" +# private = "" + +# The provider MUST support OpenID Connect with .well-known discovery +# Most notably, GitHub does not support this +# Redirect URLs in your OAuth provider can be set to this: +# /oauth/sso//callback* +# The asterisk is important, as it allows for any query parameters to be passed +# Authentik for example uses regex so it can be set to (regex): +# /oauth/sso//callback.* +# [[oidc.providers]] +# name = "CPlusPatch ID" +# id = "cpluspatch-id" +# This MUST match the provider's issuer URI, including the trailing slash (or lack thereof) +# url = "https://id.cpluspatch.com/application/o/versia-testing/" +# client_id = "XXXX" +# client_secret = "XXXXX" +# icon = "https://cpluspatch.com/images/icons/logo.svg" diff --git a/config/config.schema.json b/config/config.schema.json index ac4b4375..5df026bb 100644 --- a/config/config.schema.json +++ b/config/config.schema.json @@ -185,75 +185,6 @@ }, "additionalProperties": false }, - "oidc": { - "type": "object", - "properties": { - "forced": { - "type": "boolean", - "default": false - }, - "allow_registration": { - "type": "boolean", - "default": true - }, - "providers": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "minLength": 1 - }, - "id": { - "type": "string", - "minLength": 1 - }, - "url": { - "type": "string", - "minLength": 1 - }, - "client_id": { - "type": "string", - "minLength": 1 - }, - "client_secret": { - "type": "string", - "minLength": 1 - }, - "icon": { - "type": "string", - "minLength": 1 - } - }, - "required": [ - "name", - "id", - "url", - "client_id", - "client_secret" - ], - "additionalProperties": false - }, - "default": [] - }, - "keys": { - "type": "object", - "properties": { - "public": { - "type": "string", - "minLength": 1 - }, - "private": { - "type": "string", - "minLength": 1 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, "http": { "type": "object", "properties": { @@ -4049,12 +3980,10 @@ "redis", "sonic", "signups", - "oidc", "http", "smtp", "filters", - "ratelimits", - "plugins" + "ratelimits" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/config-manager/config.type.ts b/packages/config-manager/config.type.ts index cc7c2344..c7c7e757 100644 --- a/packages/config-manager/config.type.ts +++ b/packages/config-manager/config.type.ts @@ -120,33 +120,6 @@ export const configValidator = z rules: z.array(z.string()).default([]), }) .strict(), - oidc: z - .object({ - forced: z.boolean().default(false), - allow_registration: z.boolean().default(true), - providers: z - .array( - z - .object({ - name: z.string().min(1), - id: z.string().min(1), - url: z.string().min(1), - client_id: z.string().min(1), - client_secret: z.string().min(1), - icon: z.string().min(1).optional(), - }) - .strict(), - ) - .default([]), - keys: z - .object({ - public: z.string().min(1).optional(), - private: z.string().min(1).optional(), - }) - .strict() - .optional(), - }) - .strict(), http: z .object({ base_url: z.string().min(1).default("http://versia.social"), @@ -727,7 +700,8 @@ export const configValidator = z ), config: z.record(z.string(), z.any()).optional(), }) - .strict(), + .strict() + .optional(), }) .strict(); diff --git a/packages/database-interface/user.ts b/packages/database-interface/user.ts index c39f1243..b6bbd971 100644 --- a/packages/database-interface/user.ts +++ b/packages/database-interface/user.ts @@ -398,7 +398,14 @@ export class User extends BaseInterface { return this.update(this.data); } - public async getLinkedOidcAccounts(): Promise< + public async getLinkedOidcAccounts( + providers: { + id: string; + name: string; + url: string; + icon?: string; + }[], + ): Promise< { id: string; name: string; @@ -414,7 +421,7 @@ export class User extends BaseInterface { return accounts .map((account) => { - const issuer = config.oidc.providers.find( + const issuer = providers.find( (provider) => provider.id === account.issuerId, ); diff --git a/plugins/openid/routes/sso/index.ts b/plugins/openid/routes/sso/index.ts index 4ace8876..feaa6711 100644 --- a/plugins/openid/routes/sso/index.ts +++ b/plugins/openid/routes/sso/index.ts @@ -69,7 +69,9 @@ export default (plugin: PluginType) => { ); } - const linkedAccounts = await user.getLinkedOidcAccounts(); + const linkedAccounts = await user.getLinkedOidcAccounts( + context.get("pluginConfig").providers, + ); return context.json( linkedAccounts.map((account) => ({