diff --git a/bewcloud.config.sample.ts b/bewcloud.config.sample.ts index b2b86c8..67e44b6 100644 --- a/bewcloud.config.sample.ts +++ b/bewcloud.config.sample.ts @@ -11,6 +11,7 @@ const config: PartialDeep = { // allowedCookieDomains: ['example.com', 'example.net'], // Can be set to allow more than the baseUrl's domain for session cookies // skipCookieDomainSecurity: true, // If true, the cookie domain will not be strictly set and checked against. This skipping slightly reduces security, but is usually necessary for reverse proxies like Cloudflare Tunnel // enableSingleSignOn: false, // If true, single sign-on will be enabled + // allowSignupsViaSingleSignOn: false, // If true, signups via single sign-on will be allowed, overriding allowSignups // singleSignOnUrl: '', // The Discovery URL (AKA Issuer) of the identity/single sign-on provider // singleSignOnEmailAttribute: 'email', // The attribute to prefer as email of the identity/single sign-on provider // singleSignOnScopes: ['openid', 'email'], // The scopes to request from the identity/single sign-on provider diff --git a/lib/config.ts b/lib/config.ts index f9b1f33..42c4cc6 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -16,6 +16,7 @@ export class AppConfig { allowedCookieDomains: [], skipCookieDomainSecurity: false, enableSingleSignOn: false, + allowSignupsViaSingleSignOn: false, singleSignOnUrl: '', singleSignOnEmailAttribute: 'email', singleSignOnScopes: ['openid', 'email'], @@ -117,18 +118,13 @@ export class AppConfig { return this.config; } - static async isSignupAllowed(): Promise { + static async isSignupAllowed({ viaSingleSignOn = false }: { viaSingleSignOn?: boolean } = {}): Promise { await this.loadConfig(); - const areSignupsAllowed = this.config.auth.allowSignups; - + const areSignupsAllowed = viaSingleSignOn && !this.config.auth.allowSignups ? this.config.auth.allowSingleSignOnSignups : this.config.auth.allowSignups; const areThereAdmins = await UserModel.isThereAnAdmin(); - if (areSignupsAllowed || !areThereAdmins) { - return true; - } - - return false; + return areSignupsAllowed || !areThereAdmins; } static async isAppEnabled(app: OptionalApp): Promise { diff --git a/lib/models/oidc.ts b/lib/models/oidc.ts index 3010aef..fb09070 100644 --- a/lib/models/oidc.ts +++ b/lib/models/oidc.ts @@ -169,7 +169,7 @@ export class OidcModel { throw new Error(`Missing user/${emailAttribute}`); } - const isSignupAllowed = await AppConfig.isSignupAllowed(); + const isSignupAllowed = await AppConfig.isSignupAllowed({ viaSingleSignOn: true }); const isThereAnAdmin = await UserModel.isThereAnAdmin(); // Confirm the user exists (or signup if allowed) @@ -181,6 +181,10 @@ export class OidcModel { } if (!user) { + if (!config.auth.allowSignupsViaSingleSignOn) { + throw new Error('Sign up via SSO is not allowed!'); + } + throw new Error('There was a problem signing up or logging in!'); } diff --git a/lib/types.ts b/lib/types.ts index 65961d1..e05306c 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -159,6 +159,8 @@ export interface Config { skipCookieDomainSecurity: boolean; /** If true, single sign-on will be enabled */ enableSingleSignOn: boolean; + /** If true, signups via single sign-on will be allowed, overriding allowSignups */ + allowSignupsViaSingleSignOn: boolean; /** The Discovery URL (AKA Issuer) of the identity/single sign-on provider */ singleSignOnUrl: string; /** The attribute to prefer as email of the identity/single sign-on provider */