mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Add setting to OAuth handlers to skip local 2FA authentication (#16594)
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>
This commit is contained in:
		| @@ -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"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -181,6 +181,7 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source { | ||||
| 		OpenIDConnectAutoDiscoveryURL: form.OpenIDConnectAutoDiscoveryURL, | ||||
| 		CustomURLMapping:              customURLMapping, | ||||
| 		IconURL:                       form.Oauth2IconURL, | ||||
| 		SkipLocalTwoFA:                form.SkipLocalTwoFA, | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
| 		} | ||||
|   | ||||
| @@ -24,6 +24,7 @@ type Source struct { | ||||
| 	OpenIDConnectAutoDiscoveryURL string | ||||
| 	CustomURLMapping              *CustomURLMapping | ||||
| 	IconURL                       string | ||||
| 	SkipLocalTwoFA                bool | ||||
|  | ||||
| 	// reference to the loginSource | ||||
| 	loginSource *models.LoginSource | ||||
|   | ||||
| @@ -66,6 +66,7 @@ type AuthenticationForm struct { | ||||
| 	Oauth2EmailURL                string | ||||
| 	Oauth2IconURL                 string | ||||
| 	Oauth2Tenant                  string | ||||
| 	SkipLocalTwoFA                bool | ||||
| 	SSPIAutoCreateUsers           bool | ||||
| 	SSPIAutoActivateUsers         bool | ||||
| 	SSPIStripDomainNames          bool | ||||
|   | ||||
| @@ -255,6 +255,13 @@ | ||||
| 						<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"> | ||||
|   | ||||
| @@ -28,6 +28,13 @@ | ||||
| 		<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"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user