From d6cddbd0706625435bc4f30781e457b84edadcca Mon Sep 17 00:00:00 2001 From: nkrapp Date: Thu, 17 Nov 2022 17:21:27 +0100 Subject: [PATCH] Add setting to force login through openid This PR aims to add a setting that skips the normal login and redirects automatically to the openID login/the configured openID provider The desired behavior can be observed at https://gitea.opensuse.org/ BLENDER NOTE: this is is PR #21851, in the hope that this will be merged upstream. --- cmd/admin.go | 8 +++++ docs/content/doc/usage/command-line.en-us.md | 2 ++ options/locale/locale_de-DE.ini | 2 ++ options/locale/locale_en-US.ini | 2 ++ routers/web/admin/auths.go | 1 + routers/web/auth/auth.go | 31 +++++++++++++++++++ services/auth/interface.go | 4 +++ services/auth/source/oauth2/source.go | 1 + .../auth/source/oauth2/source_authenticate.go | 4 +++ services/forms/auth_form.go | 1 + templates/admin/auth/edit.tmpl | 7 +++++ templates/admin/auth/source/oauth.tmpl | 7 +++++ 12 files changed, 70 insertions(+) diff --git a/cmd/admin.go b/cmd/admin.go index a662011f9c07..484507a6d525 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -362,6 +362,10 @@ var ( Value: "", Usage: "Group Claim value for restricted users", }, + cli.BoolFlag{ + Name: "force-oauth", + Usage: "set to force all logins to the configured oauth provider", + }, } microcmdAuthUpdateOauth = cli.Command{ @@ -826,6 +830,7 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source { CustomURLMapping: customURLMapping, IconURL: c.String("icon-url"), SkipLocalTwoFA: c.Bool("skip-local-2fa"), + ForceOAuth: c.Bool("force-oauth"), Scopes: c.StringSlice("scopes"), RequiredClaimName: c.String("required-claim-name"), RequiredClaimValue: c.String("required-claim-value"), @@ -914,6 +919,9 @@ func runUpdateOauth(c *cli.Context) error { if c.IsSet("restricted-group") { oAuth2Config.RestrictedGroup = c.String("restricted-group") } + if c.IsSet("force-oauth") { + oAuth2Config.ForceOAuth = c.BoolT("force-oauth") + } // update custom URL mapping customURLMapping := &oauth2.CustomURLMapping{} diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index 5f05bc4c3be3..eaa5ebdf2119 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -130,6 +130,7 @@ Admin operations: - `--custom-email-url`: Use a custom Email URL (option for GitHub). - `--icon-url`: Custom icon URL for OAuth2 login source. - `--skip-local-2fa`: Allow source to override local 2FA. (Optional) + - `--force-oauth`: Automatically redirect sign in to this OAuth provider (Optional) - `--scopes`: Additional scopes to request for this OAuth2 source. (Optional) - `--required-claim-name`: Claim name that has to be set to allow users to login with this source. (Optional) - `--required-claim-value`: Claim value that has to be set to allow users to login with this source. (Optional) @@ -153,6 +154,7 @@ Admin operations: - `--custom-email-url`: Use a custom Email URL (option for GitHub). - `--icon-url`: Custom icon URL for OAuth2 login source. - `--skip-local-2fa`: Allow source to override local 2FA. (Optional) + - `--force-oauth`: Automatically redirect sign in to this OAuth provider (Optional) - `--scopes`: Additional scopes to request for this OAuth2 source. - `--required-claim-name`: Claim name that has to be set to allow users to login with this source. (Optional) - `--required-claim-value`: Claim value that has to be set to allow users to login with this source. (Optional) diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index d8874fd5fa82..c74d36697de7 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -2666,6 +2666,8 @@ auths.oauth2_profileURL=Profil-URL auths.oauth2_emailURL=E-Mail-URL auths.skip_local_two_fa=Lokale 2FA überspringen auths.skip_local_two_fa_helper=Leer lassen bedeutet, dass lokale User die 2FA immer noch bestehen müssen, um sich anzumelden +auths.force_o_auth=Anmelden durch diese Quelle erzwingen +auths.force_o_auth_helper=Setzen um Anmeldungen automatisch auf diesen OAuth Anbieter umzuleiten auths.oauth2_tenant=Inhaber auths.oauth2_scopes=Zusätzliche Bereiche auths.oauth2_required_claim_name=Benötigter Claim-Name diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 74ba85ca9016..ff1cb0bad3ee 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2739,6 +2739,8 @@ auths.oauth2_profileURL = Profile URL auths.oauth2_emailURL = Email URL auths.skip_local_two_fa = Skip local 2FA auths.skip_local_two_fa_helper = Leaving unset means local users with 2FA set will still have to pass 2FA to log on +auths.force_o_auth = Force login via this authentication +auths.force_o_auth_helper = Set this to automatically redirect sign in to this OAuth provider auths.oauth2_tenant = Tenant auths.oauth2_scopes = Additional Scopes auths.oauth2_required_claim_name = Required Claim Name diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index 1bc166902c7b..eeed49b94b70 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -201,6 +201,7 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source { RequiredClaimName: form.Oauth2RequiredClaimName, RequiredClaimValue: form.Oauth2RequiredClaimValue, SkipLocalTwoFA: form.SkipLocalTwoFA, + ForceOAuth: form.ForceOAuth, GroupClaimName: form.Oauth2GroupClaimName, RestrictedGroup: form.Oauth2RestrictedGroup, AdminGroup: form.Oauth2AdminGroup, diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go index 48b7dc6862ae..a213c695d3ed 100644 --- a/routers/web/auth/auth.go +++ b/routers/web/auth/auth.go @@ -137,6 +137,32 @@ func checkAutoLogin(ctx *context.Context) bool { return false } +func checkForceOAuth(ctx *context.Context) bool { + // Check if authentication is forced to OAuth + + authSources, err := auth.GetActiveOAuth2ProviderSources() + if err != nil { + return false + } + + var OAuthList []int64 + + for _, source := range authSources { + if forced, ok := source.Cfg.(auth_service.ForceOAuth); ok && forced.IsOAuthForced() { + OAuthList = append(OAuthList, source.ID) + app, err := auth.GetOAuth2ApplicationByID(ctx, OAuthList[0]) + if err != nil { + return false + } + url := app.PrimaryRedirectURI() + ctx.Redirect(url) + return true + } + } + + return false +} + // SignIn render sign in page func SignIn(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("sign_in") @@ -146,6 +172,11 @@ func SignIn(ctx *context.Context) { return } + // Check if authentication is forced to OAuth + if checkForceOAuth(ctx) { + return + } + orderedOAuth2Names, oauth2Providers, err := oauth2.GetActiveOAuth2Providers() if err != nil { ctx.ServerError("UserSignIn", err) diff --git a/services/auth/interface.go b/services/auth/interface.go index f2f1aaf39cb0..0ad2095381ef 100644 --- a/services/auth/interface.go +++ b/services/auth/interface.go @@ -59,6 +59,10 @@ type LocalTwoFASkipper interface { IsSkipLocalTwoFA() bool } +type ForceOAuth interface { + IsOAuthForced() bool +} + // SynchronizableSource represents a source that can synchronize users type SynchronizableSource interface { Sync(ctx context.Context, updateExisting bool) error diff --git a/services/auth/source/oauth2/source.go b/services/auth/source/oauth2/source.go index 0abebc04ecfd..62167f6d2c80 100644 --- a/services/auth/source/oauth2/source.go +++ b/services/auth/source/oauth2/source.go @@ -23,6 +23,7 @@ type Source struct { OpenIDConnectAutoDiscoveryURL string CustomURLMapping *CustomURLMapping IconURL string + ForceOAuth bool `json:",omitempty"` Scopes []string RequiredClaimName string diff --git a/services/auth/source/oauth2/source_authenticate.go b/services/auth/source/oauth2/source_authenticate.go index e3e2a9e192f5..ac756ae16410 100644 --- a/services/auth/source/oauth2/source_authenticate.go +++ b/services/auth/source/oauth2/source_authenticate.go @@ -13,5 +13,9 @@ func (source *Source) Authenticate(user *user_model.User, login, password string return db.Authenticate(user, login, password) } +func (source *Source) IsOAuthForced() bool { + return source.ForceOAuth +} + // NB: Oauth2 does not implement LocalTwoFASkipper for password authentication // as its password authentication drops to db authentication diff --git a/services/forms/auth_form.go b/services/forms/auth_form.go index 0cede07f951e..4ef25780dac4 100644 --- a/services/forms/auth_form.go +++ b/services/forms/auth_form.go @@ -73,6 +73,7 @@ type AuthenticationForm struct { Oauth2AdminGroup string Oauth2RestrictedGroup string SkipLocalTwoFA bool + ForceOAuth bool SSPIAutoCreateUsers bool SSPIAutoActivateUsers bool SSPIStripDomainNames bool diff --git a/templates/admin/auth/edit.tmpl b/templates/admin/auth/edit.tmpl index bf9d53152c2e..f7c104bf08f9 100644 --- a/templates/admin/auth/edit.tmpl +++ b/templates/admin/auth/edit.tmpl @@ -299,6 +299,13 @@

{{.locale.Tr "admin.auths.skip_local_two_fa_helper"}}

+
+
+ + +

{{.locale.Tr "admin.auths.force_o_auth_helper"}}

+
+
diff --git a/templates/admin/auth/source/oauth.tmpl b/templates/admin/auth/source/oauth.tmpl index 166373a32489..535c0473e4f5 100644 --- a/templates/admin/auth/source/oauth.tmpl +++ b/templates/admin/auth/source/oauth.tmpl @@ -35,6 +35,13 @@

{{.locale.Tr "admin.auths.skip_local_two_fa_helper"}}

+
+
+ + +

{{.locale.Tr "admin.auths.force_o_auth_helper"}}

+
+