]> source.dussan.org Git - gitea.git/commitdiff
Add setting to OAuth handlers to skip local 2FA authentication (#16594)
authorzeripath <art27@cantab.net>
Fri, 10 Sep 2021 16:37:57 +0000 (17:37 +0100)
committerGitHub <noreply@github.com>
Fri, 10 Sep 2021 16:37:57 +0000 (18:37 +0200)
This PR adds a setting to OAuth and OpenID login sources to allow the source to
skip local 2FA authentication.

Fix #13939

Signed-off-by: Andrew Thornton <art27@cantab.net>
cmd/admin.go
options/locale/locale_en-US.ini
routers/web/admin/auths.go
routers/web/user/auth.go
services/auth/source/oauth2/source.go
services/forms/auth_form.go
templates/admin/auth/edit.tmpl
templates/admin/auth/source/oauth.tmpl

index 94e78186c902fcc730ae01b899827187e69e31dd..cfc297c47464674264bdc962bd0ce1b55c1f91a8 100644 (file)
@@ -288,6 +288,10 @@ var (
                        Value: "",
                        Usage: "Custom icon URL for OAuth2 login source",
                },
+               cli.BoolFlag{
+                       Name:  "skip-local-2fa",
+                       Usage: "Set to true to skip local 2fa for users authenticated by this source",
+               },
        }
 
        microcmdAuthUpdateOauth = cli.Command{
@@ -616,6 +620,7 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source {
                OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
                CustomURLMapping:              customURLMapping,
                IconURL:                       c.String("icon-url"),
+               SkipLocalTwoFA:                c.Bool("skip-local-2fa"),
        }
 }
 
index 17701094d786d640a089c14cc4e4e83310715291..9ebd2e7a5fa6756aaa3c898ea0d3ff733e3d166c 100644 (file)
@@ -2456,6 +2456,8 @@ auths.oauth2_tokenURL = Token URL
 auths.oauth2_authURL = Authorize URL
 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.oauth2_tenant = Tenant
 auths.enable_auto_register = Enable Auto Registration
 auths.sspi_auto_create_users = Automatically create users
index 342318e04e9b50fc598ca29f612842b730f9fd85..b2879d7c4f66c38a100fe30913618fb4776290ad 100644 (file)
@@ -181,6 +181,7 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source {
                OpenIDConnectAutoDiscoveryURL: form.OpenIDConnectAutoDiscoveryURL,
                CustomURLMapping:              customURLMapping,
                IconURL:                       form.Oauth2IconURL,
+               SkipLocalTwoFA:                form.SkipLocalTwoFA,
        }
 }
 
index 313a583004a575d26e5aef5036022870eac941c8..38e0d989b8d56cd5a9b206ca8ae2932548388168 100644 (file)
@@ -574,7 +574,7 @@ func SignInOAuth(ctx *context.Context) {
        user, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req, ctx.Resp)
        if err == nil && user != nil {
                // we got the user without going through the whole OAuth2 authentication flow again
-               handleOAuth2SignIn(ctx, user, gothUser)
+               handleOAuth2SignIn(ctx, loginSource, user, gothUser)
                return
        }
 
@@ -660,7 +660,7 @@ func SignInOAuthCallback(ctx *context.Context) {
                }
        }
 
-       handleOAuth2SignIn(ctx, u, gothUser)
+       handleOAuth2SignIn(ctx, loginSource, u, gothUser)
 }
 
 func getUserName(gothUser *goth.User) string {
@@ -702,18 +702,22 @@ func updateAvatarIfNeed(url string, u *models.User) {
        }
 }
 
-func handleOAuth2SignIn(ctx *context.Context, u *models.User, gothUser goth.User) {
+func handleOAuth2SignIn(ctx *context.Context, source *models.LoginSource, u *models.User, gothUser goth.User) {
        updateAvatarIfNeed(gothUser.AvatarURL, u)
 
-       // If this user is enrolled in 2FA, we can't sign the user in just yet.
-       // Instead, redirect them to the 2FA authentication page.
-       _, err := models.GetTwoFactorByUID(u.ID)
-       if err != nil {
-               if !models.IsErrTwoFactorNotEnrolled(err) {
+       needs2FA := false
+       if !source.Cfg.(*oauth2.Source).SkipLocalTwoFA {
+               _, err := models.GetTwoFactorByUID(u.ID)
+               if err != nil && !models.IsErrTwoFactorNotEnrolled(err) {
                        ctx.ServerError("UserSignIn", err)
                        return
                }
+               needs2FA = err == nil
+       }
 
+       // If this user is enrolled in 2FA and this source doesn't override it,
+       // we can't sign the user in just yet. Instead, redirect them to the 2FA authentication page.
+       if !needs2FA {
                if err := ctx.Session.Set("uid", u.ID); err != nil {
                        log.Error("Error setting uid in session: %v", err)
                }
index 40d8973b4b2ce481bb2a9a8035857df493087a16..7b22383d7ed6dac169f10ed334dadf32356a3c7e 100644 (file)
@@ -24,6 +24,7 @@ type Source struct {
        OpenIDConnectAutoDiscoveryURL string
        CustomURLMapping              *CustomURLMapping
        IconURL                       string
+       SkipLocalTwoFA                bool
 
        // reference to the loginSource
        loginSource *models.LoginSource
index b45ea6ea124f76297827ddb3aaf901f18e83bc35..229728cf7daf36adda2299d55a6278150b51717e 100644 (file)
@@ -66,6 +66,7 @@ type AuthenticationForm struct {
        Oauth2EmailURL                string
        Oauth2IconURL                 string
        Oauth2Tenant                  string
+       SkipLocalTwoFA                bool
        SSPIAutoCreateUsers           bool
        SSPIAutoActivateUsers         bool
        SSPIStripDomainNames          bool
index 109186a17821f156cca8cc1547d36ff75637a1d7..3e21710353e3547d6d1f8f38e01acead03dbe442 100644 (file)
                                                <label for="open_id_connect_auto_discovery_url">{{.i18n.Tr "admin.auths.openIdConnectAutoDiscoveryURL"}}</label>
                                                <input id="open_id_connect_auto_discovery_url" name="open_id_connect_auto_discovery_url" value="{{$cfg.OpenIDConnectAutoDiscoveryURL}}">
                                        </div>
+                                       <div class="optional field">
+                                               <div class="ui checkbox">
+                                                       <label for="skip_local_two_fa"><strong>{{.i18n.Tr "admin.auths.skip_local_two_fa"}}</strong></label>
+                                                       <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if $cfg.SkipLocalTwoFA}}checked{{end}}>
+                                                       <p class="help">{{.i18n.Tr "admin.auths.skip_local_two_fa_helper"}}</p>
+                                               </div>
+                                       </div>
 
                                        <div class="oauth2_use_custom_url inline field">
                                                <div class="ui checkbox">
index b19fe3d42825de5077ed067efd03ef221a0eb8de..6e91da14e24f0a9e2ba8816db64ccc0b51d98db3 100644 (file)
                <label for="open_id_connect_auto_discovery_url">{{.i18n.Tr "admin.auths.openIdConnectAutoDiscoveryURL"}}</label>
                <input id="open_id_connect_auto_discovery_url" name="open_id_connect_auto_discovery_url" value="{{.open_id_connect_auto_discovery_url}}">
        </div>
+       <div class="optional field">
+               <div class="ui checkbox">
+                       <label for="skip_local_two_fa"><strong>{{.i18n.Tr "admin.auths.skip_local_two_fa"}}</strong></label>
+                       <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if .skip_local_two_fa}}checked{{end}}>
+                       <p class="help">{{.i18n.Tr "admin.auths.skip_local_two_fa_helper"}}</p>
+               </div>
+       </div>
 
        <div class="oauth2_use_custom_url inline field">
                <div class="ui checkbox">