265 lines
16 KiB
Diff
265 lines
16 KiB
Diff
diff --git a/cypress/e2e/frontend/manage/config/config-manager.cy.ts b/cypress/e2e/frontend/manage/config/config-manager.cy.ts
|
|
index b4e3d94b..4ecccf7b 100644
|
|
--- a/cypress/e2e/frontend/manage/config/config-manager.cy.ts
|
|
+++ b/cypress/e2e/frontend/manage/config/config-manager.cy.ts
|
|
@@ -143,6 +143,7 @@ context('Config Manager', () => {
|
|
['New commenters must confirm their email', ''],
|
|
['New users must confirm their email', '✔'],
|
|
['Enable registration of new users', '✔'],
|
|
+ ['Enable registration of new users via SSO', '✔'],
|
|
['Show login dialog for unauthenticated users', '✔'],
|
|
['Enable commenter registration via external provider', '✔'],
|
|
['Enable local commenter registration', '✔'],
|
|
@@ -182,6 +183,7 @@ context('Config Manager', () => {
|
|
cy.get('@configEdit').find('#auth_signup_confirm_commenter') .should('not.be.checked').clickLabel().should('be.checked');
|
|
cy.get('@configEdit').find('#auth_signup_confirm_user') .should('be.checked') .clickLabel().should('not.be.checked');
|
|
cy.get('@configEdit').find('#auth_signup_enabled') .should('be.checked') .clickLabel().should('not.be.checked');
|
|
+ cy.get('@configEdit').find('#auth_signup_sso_enabled') .should('be.checked') .clickLabel().should('not.be.checked');
|
|
cy.get('@configEdit').find('#domain_defaults_comments_deletion_author') .should('be.checked') .clickLabel().should('not.be.checked');
|
|
cy.get('@configEdit').find('#domain_defaults_comments_deletion_moderator').should('be.checked') .clickLabel().should('not.be.checked');
|
|
cy.get('@configEdit').find('#domain_defaults_comments_editing_author') .should('be.checked') .clickLabel().should('not.be.checked');
|
|
@@ -219,6 +221,7 @@ context('Config Manager', () => {
|
|
['New commenters must confirm their email', '✔'],
|
|
['New users must confirm their email', ''],
|
|
['Enable registration of new users', ''],
|
|
+ ['Enable registration of new users via SSO', ''],
|
|
['Show login dialog for unauthenticated users', ''],
|
|
['Enable commenter registration via external provider', ''],
|
|
['Enable local commenter registration', '✔'],
|
|
@@ -283,6 +286,7 @@ context('Config Manager', () => {
|
|
[InstanceConfigKey.authSignupConfirmCommenter]: false,
|
|
[InstanceConfigKey.authSignupConfirmUser]: false,
|
|
[InstanceConfigKey.authSignupEnabled]: false,
|
|
+ [InstanceConfigKey.authSsoSignupEnabled]: false,
|
|
[InstanceConfigKey.domainDefaultsCommentDeletionAuthor]: false,
|
|
[InstanceConfigKey.domainDefaultsCommentDeletionModerator]: true,
|
|
[InstanceConfigKey.domainDefaultsCommentEditingAuthor]: true,
|
|
@@ -311,6 +315,7 @@ context('Config Manager', () => {
|
|
['New commenters must confirm their email', ''],
|
|
['New users must confirm their email', ''],
|
|
['Enable registration of new users', ''],
|
|
+ ['Enable registration of new users via SSO', ''],
|
|
['Show login dialog for unauthenticated users', ''],
|
|
['Enable commenter registration via external provider', ''],
|
|
['Enable local commenter registration', ''],
|
|
diff --git a/cypress/support/cy-utils.ts b/cypress/support/cy-utils.ts
|
|
index 4775dce0..c0a87913 100644
|
|
--- a/cypress/support/cy-utils.ts
|
|
+++ b/cypress/support/cy-utils.ts
|
|
@@ -199,6 +199,7 @@ export enum InstanceConfigKey {
|
|
authSignupConfirmCommenter = 'auth.signup.confirm.commenter',
|
|
authSignupConfirmUser = 'auth.signup.confirm.user',
|
|
authSignupEnabled = 'auth.signup.enabled',
|
|
+ authSsoSignupEnabled = 'auth.signup.sso.enabled',
|
|
integrationsUseGravatar = 'integrations.useGravatar',
|
|
operationNewOwnerEnabled = 'operation.newOwner.enabled',
|
|
// Domain defaults
|
|
diff --git a/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md b/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
|
|
index 35acc2ba..9427c016 100644
|
|
--- a/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
|
|
+++ b/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
|
|
@@ -7,6 +7,7 @@ tags:
|
|
- administration
|
|
- Administration UI
|
|
seeAlso:
|
|
+ - auth.signup.sso.enabled
|
|
- domain.defaults.signup.enablefederated
|
|
- domain.defaults.signup.enablelocal
|
|
- domain.defaults.signup.enablesso
|
|
diff --git a/docs/content/configuration/backend/dynamic/auth.signup.sso.enabled.en.md b/docs/content/configuration/backend/dynamic/auth.signup.sso.enabled.en.md
|
|
new file mode 100644
|
|
index 00000000..66748b51
|
|
--- /dev/null
|
|
+++ b/docs/content/configuration/backend/dynamic/auth.signup.sso.enabled.en.md
|
|
@@ -0,0 +1,23 @@
|
|
+---
|
|
+title: Enable registration of new users via SSO
|
|
+description: auth.signup.sso.enabled
|
|
+tags:
|
|
+ - configuration
|
|
+ - dynamic configuration
|
|
+ - administration
|
|
+ - Administration UI
|
|
+seeAlso:
|
|
+ - auth.signup.enabled
|
|
+ - domain.defaults.signup.enablefederated
|
|
+ - domain.defaults.signup.enablelocal
|
|
+ - domain.defaults.signup.enablesso
|
|
+---
|
|
+
|
|
+This [dynamic configuration](/configuration/backend/dynamic) parameter controls whether new users are allowed to register in the Administration UI of Comentario via SSO.
|
|
+
|
|
+<!--more-->
|
|
+
|
|
+* If set to `On`, new users can register in the Administration UI via SSO.
|
|
+* If set to `Off`, new user registrations via SSO are forbidden.
|
|
+
|
|
+This setting applies only to the Administration UI.
|
|
diff --git a/e2e/plugin/db-seed.sql b/e2e/plugin/db-seed.sql
|
|
index 1e02e554..69aaec98 100644
|
|
--- a/e2e/plugin/db-seed.sql
|
|
+++ b/e2e/plugin/db-seed.sql
|
|
@@ -5,6 +5,7 @@ values
|
|
('auth.signup.confirm.commenter', 'false', '0001-01-01 00:00:00.000000'),
|
|
('auth.signup.confirm.user', 'true', '0001-01-01 00:00:00.000000'),
|
|
('auth.signup.enabled', 'true', '0001-01-01 00:00:00.000000'),
|
|
+ ('auth.signup.sso.enabled', 'true', '0001-01-01 00:00:00.000000'),
|
|
('domain.defaults.comments.deletion.author', 'true', '0001-01-01 00:00:00.000000'),
|
|
('domain.defaults.comments.deletion.moderator', 'true', '0001-01-01 00:00:00.000000'),
|
|
('domain.defaults.comments.editing.author', 'true', '0001-01-01 00:00:00.000000'),
|
|
diff --git a/frontend/app/_models/config.ts b/frontend/app/_models/config.ts
|
|
index 11ddd516..0ded8049 100644
|
|
--- a/frontend/app/_models/config.ts
|
|
+++ b/frontend/app/_models/config.ts
|
|
@@ -30,6 +30,7 @@ export enum InstanceConfigItemKey {
|
|
authSignupConfirmCommenter = 'auth.signup.confirm.commenter',
|
|
authSignupConfirmUser = 'auth.signup.confirm.user',
|
|
authSignupEnabled = 'auth.signup.enabled',
|
|
+ authSsoSignupEnabled = 'auth.signup.sso.enabled',
|
|
integrationsUseGravatar = 'integrations.useGravatar',
|
|
operationNewOwnerEnabled = 'operation.newOwner.enabled',
|
|
// Domain defaults
|
|
diff --git a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts
|
|
index b282586c..1eaf1085 100644
|
|
--- a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts
|
|
+++ b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts
|
|
@@ -21,6 +21,7 @@ describe('DynConfigItemNamePipe', () => {
|
|
{in: 'auth.signup.confirm.commenter', want: 'New commenters must confirm their email'},
|
|
{in: 'auth.signup.confirm.user', want: 'New users must confirm their email'},
|
|
{in: 'auth.signup.enabled', want: 'Enable registration of new users'},
|
|
+ {in: 'auth.signup.sso.enabled', want: 'Enable registration of new users via SSO' },
|
|
{in: 'integrations.useGravatar', want: 'Use Gravatar for user avatars'},
|
|
{in: 'operation.newOwner.enabled', want: 'Non-owner users can add domains'},
|
|
// Domain defaults
|
|
diff --git a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts
|
|
index 7d3dc792..723e8149 100644
|
|
--- a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts
|
|
+++ b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts
|
|
@@ -12,6 +12,7 @@ export class DynConfigItemNamePipe implements PipeTransform {
|
|
[InstanceConfigItemKey.authSignupConfirmCommenter]: $localize`New commenters must confirm their email`,
|
|
[InstanceConfigItemKey.authSignupConfirmUser]: $localize`New users must confirm their email`,
|
|
[InstanceConfigItemKey.authSignupEnabled]: $localize`Enable registration of new users`,
|
|
+ [InstanceConfigItemKey.authSsoSignupEnabled]: $localize`Enable registration of new users via SSO`,
|
|
[InstanceConfigItemKey.integrationsUseGravatar]: $localize`Use Gravatar for user avatars`,
|
|
[InstanceConfigItemKey.operationNewOwnerEnabled]: $localize`Non-owner users can add domains`,
|
|
// Domain defaults
|
|
diff --git a/internal/api/restapi/handlers/oauth.go b/internal/api/restapi/handlers/oauth.go
|
|
index 8c5129f2..3837d229 100644
|
|
--- a/internal/api/restapi/handlers/oauth.go
|
|
+++ b/internal/api/restapi/handlers/oauth.go
|
|
@@ -220,7 +220,7 @@ func AuthOauthCallback(params api_general.AuthOauthCallbackParams) middleware.Re
|
|
var cfgItem *data.DynConfigItem
|
|
if domain == nil {
|
|
// Frontend signup
|
|
- cfgItem, err = svc.Services.DynConfigService().Get(data.ConfigKeyAuthSignupEnabled)
|
|
+ cfgItem, err = svc.Services.DynConfigService().Get(data.ConfigKeyAuthSsoSignupEnabled)
|
|
|
|
} else if sso {
|
|
// SSO embed signup
|
|
@@ -248,9 +248,29 @@ func AuthOauthCallback(params api_general.AuthOauthCallbackParams) middleware.Re
|
|
return errors.New(errMessage)
|
|
}
|
|
|
|
+ // Check if the superuser claim is set
|
|
+ superuser := false
|
|
+ if fidp, ok := config.FederatedIdProviders[models.FederatedIdpID(idpID)]; ok {
|
|
+ if fidp.SuperuserClaim != "" {
|
|
+ if raw, ok := fedUser.RawData[fidp.SuperuserClaim]; ok {
|
|
+ switch v := raw.(type) {
|
|
+ case bool:
|
|
+ if v {
|
|
+ superuser = true
|
|
+ }
|
|
+ case string:
|
|
+ if v == "true" || v == "1" {
|
|
+ superuser = true
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
// Insert a new user
|
|
user = data.NewUser(fedUser.Email, fedUserName).
|
|
WithConfirmed(true). // Confirm the user right away as we trust the IdP
|
|
+ WithSuperuser(superuser).
|
|
WithLangFromReq(params.HTTPRequest).
|
|
WithSignup(params.HTTPRequest, authSession.Host, !config.ServerConfig.Logging.FullIPs).
|
|
WithFederated(fedUser.UserID, idpID).
|
|
diff --git a/internal/config/oauth.go b/internal/config/oauth.go
|
|
index 10917c44..7ba997d9 100644
|
|
--- a/internal/config/oauth.go
|
|
+++ b/internal/config/oauth.go
|
|
@@ -177,9 +177,10 @@ func oidcConfigure() error {
|
|
// Add it to the configured providers map
|
|
mid := models.FederatedIdpID(qid)
|
|
FederatedIdProviders[mid] = &data.FederatedIdentityProvider{
|
|
- ID: mid,
|
|
- Name: p.Name,
|
|
- GothName: qid,
|
|
+ ID: mid,
|
|
+ Name: p.Name,
|
|
+ GothName: qid,
|
|
+ SuperuserClaim: p.SuperuserClaim,
|
|
}
|
|
cnt++
|
|
}
|
|
diff --git a/internal/config/secrets.go b/internal/config/secrets.go
|
|
index d3e2af97..92f33f74 100644
|
|
--- a/internal/config/secrets.go
|
|
+++ b/internal/config/secrets.go
|
|
@@ -59,10 +59,11 @@ type APIKey struct {
|
|
|
|
// OIDCProvider stores OIDC provider configuration
|
|
type OIDCProvider struct {
|
|
- KeySecretURL `yaml:",inline"`
|
|
- ID string `yaml:"id"` // Unique provider ID, e.g. "keycloak"
|
|
- Name string `yaml:"name"` // Provider display name, e.g. "Keycloak"
|
|
- Scopes []string `yaml:"scopes"` // Additional scopes to request
|
|
+ KeySecretURL `yaml:",inline"`
|
|
+ ID string `yaml:"id"` // Unique provider ID, e.g. "keycloak"
|
|
+ Name string `yaml:"name"` // Provider display name, e.g. "Keycloak"
|
|
+ Scopes []string `yaml:"scopes"` // Additional scopes to request
|
|
+ SuperuserClaim string `yaml:"superuserClaim"` // Name of the OIDC claim for superusers
|
|
}
|
|
|
|
// QualifiedID returns the provider's ID prepended with the common OIDC prefix
|
|
diff --git a/internal/data/dyn_config.go b/internal/data/dyn_config.go
|
|
index 0cd0d64e..b4ff042d 100644
|
|
--- a/internal/data/dyn_config.go
|
|
+++ b/internal/data/dyn_config.go
|
|
@@ -171,6 +171,7 @@ const (
|
|
ConfigKeyAuthSignupConfirmCommenter DynConfigItemKey = "auth.signup.confirm.commenter"
|
|
ConfigKeyAuthSignupConfirmUser DynConfigItemKey = "auth.signup.confirm.user"
|
|
ConfigKeyAuthSignupEnabled DynConfigItemKey = "auth.signup.enabled"
|
|
+ ConfigKeyAuthSsoSignupEnabled DynConfigItemKey = "auth.signup.sso.enabled"
|
|
ConfigKeyIntegrationsUseGravatar DynConfigItemKey = "integrations.useGravatar"
|
|
ConfigKeyOperationNewOwnerEnabled DynConfigItemKey = "operation.newOwner.enabled"
|
|
)
|
|
@@ -204,6 +205,7 @@ var DefaultDynInstanceConfig = DynConfigMap{
|
|
ConfigKeyAuthSignupConfirmCommenter: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
|
|
ConfigKeyAuthSignupConfirmUser: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
|
|
ConfigKeyAuthSignupEnabled: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
|
|
+ ConfigKeyAuthSsoSignupEnabled: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
|
|
ConfigKeyIntegrationsUseGravatar: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionIntegrations},
|
|
ConfigKeyOperationNewOwnerEnabled: {DefaultValue: "false", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionMisc},
|
|
ConfigKeyDomainDefaultsPrefix + DomainConfigKeyCommentDeletionAuthor: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionComments},
|
|
diff --git a/internal/data/models.go b/internal/data/models.go
|
|
index 4561fad5..0b491724 100644
|
|
--- a/internal/data/models.go
|
|
+++ b/internal/data/models.go
|
|
@@ -74,9 +74,10 @@ func (sd SortDirection) ToOrderedExpression(ident string) exp.OrderedExpression
|
|
|
|
// FederatedIdentityProvider describes a federated identity provider
|
|
type FederatedIdentityProvider struct {
|
|
- ID models.FederatedIdpID // Provider ID
|
|
- Name string // Provider name
|
|
- GothName string // Name of the corresponding goth provider
|
|
+ ID models.FederatedIdpID // Provider ID
|
|
+ Name string // Provider name
|
|
+ GothName string // Name of the corresponding goth provider
|
|
+ SuperuserClaim string // Name of the OIDC claim for superusers
|
|
}
|
|
|
|
// ToDTO converts this model into an API model
|