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:
parent
51578d6418
commit
9ca0e7905c
8 changed files with 36 additions and 8 deletions
|
@ -288,6 +288,10 @@ var (
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Custom icon URL for OAuth2 login source",
|
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{
|
microcmdAuthUpdateOauth = cli.Command{
|
||||||
|
@ -616,6 +620,7 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||||
CustomURLMapping: customURLMapping,
|
CustomURLMapping: customURLMapping,
|
||||||
IconURL: c.String("icon-url"),
|
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_authURL = Authorize URL
|
||||||
auths.oauth2_profileURL = Profile URL
|
auths.oauth2_profileURL = Profile URL
|
||||||
auths.oauth2_emailURL = Email 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.oauth2_tenant = Tenant
|
||||||
auths.enable_auto_register = Enable Auto Registration
|
auths.enable_auto_register = Enable Auto Registration
|
||||||
auths.sspi_auto_create_users = Automatically create users
|
auths.sspi_auto_create_users = Automatically create users
|
||||||
|
|
|
@ -181,6 +181,7 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source {
|
||||||
OpenIDConnectAutoDiscoveryURL: form.OpenIDConnectAutoDiscoveryURL,
|
OpenIDConnectAutoDiscoveryURL: form.OpenIDConnectAutoDiscoveryURL,
|
||||||
CustomURLMapping: customURLMapping,
|
CustomURLMapping: customURLMapping,
|
||||||
IconURL: form.Oauth2IconURL,
|
IconURL: form.Oauth2IconURL,
|
||||||
|
SkipLocalTwoFA: form.SkipLocalTwoFA,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -574,7 +574,7 @@ func SignInOAuth(ctx *context.Context) {
|
||||||
user, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req, ctx.Resp)
|
user, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req, ctx.Resp)
|
||||||
if err == nil && user != nil {
|
if err == nil && user != nil {
|
||||||
// we got the user without going through the whole OAuth2 authentication flow again
|
// we got the user without going through the whole OAuth2 authentication flow again
|
||||||
handleOAuth2SignIn(ctx, user, gothUser)
|
handleOAuth2SignIn(ctx, loginSource, user, gothUser)
|
||||||
return
|
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 {
|
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)
|
updateAvatarIfNeed(gothUser.AvatarURL, u)
|
||||||
|
|
||||||
// If this user is enrolled in 2FA, we can't sign the user in just yet.
|
needs2FA := false
|
||||||
// Instead, redirect them to the 2FA authentication page.
|
if !source.Cfg.(*oauth2.Source).SkipLocalTwoFA {
|
||||||
_, err := models.GetTwoFactorByUID(u.ID)
|
_, err := models.GetTwoFactorByUID(u.ID)
|
||||||
if err != nil {
|
if err != nil && !models.IsErrTwoFactorNotEnrolled(err) {
|
||||||
if !models.IsErrTwoFactorNotEnrolled(err) {
|
|
||||||
ctx.ServerError("UserSignIn", err)
|
ctx.ServerError("UserSignIn", err)
|
||||||
return
|
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 {
|
if err := ctx.Session.Set("uid", u.ID); err != nil {
|
||||||
log.Error("Error setting uid in session: %v", err)
|
log.Error("Error setting uid in session: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ type Source struct {
|
||||||
OpenIDConnectAutoDiscoveryURL string
|
OpenIDConnectAutoDiscoveryURL string
|
||||||
CustomURLMapping *CustomURLMapping
|
CustomURLMapping *CustomURLMapping
|
||||||
IconURL string
|
IconURL string
|
||||||
|
SkipLocalTwoFA bool
|
||||||
|
|
||||||
// reference to the loginSource
|
// reference to the loginSource
|
||||||
loginSource *models.LoginSource
|
loginSource *models.LoginSource
|
||||||
|
|
|
@ -66,6 +66,7 @@ type AuthenticationForm struct {
|
||||||
Oauth2EmailURL string
|
Oauth2EmailURL string
|
||||||
Oauth2IconURL string
|
Oauth2IconURL string
|
||||||
Oauth2Tenant string
|
Oauth2Tenant string
|
||||||
|
SkipLocalTwoFA bool
|
||||||
SSPIAutoCreateUsers bool
|
SSPIAutoCreateUsers bool
|
||||||
SSPIAutoActivateUsers bool
|
SSPIAutoActivateUsers bool
|
||||||
SSPIStripDomainNames bool
|
SSPIStripDomainNames bool
|
||||||
|
|
|
@ -255,6 +255,13 @@
|
||||||
<label for="open_id_connect_auto_discovery_url">{{.i18n.Tr "admin.auths.openIdConnectAutoDiscoveryURL"}}</label>
|
<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}}">
|
<input id="open_id_connect_auto_discovery_url" name="open_id_connect_auto_discovery_url" value="{{$cfg.OpenIDConnectAutoDiscoveryURL}}">
|
||||||
</div>
|
</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="oauth2_use_custom_url inline field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
|
|
|
@ -28,6 +28,13 @@
|
||||||
<label for="open_id_connect_auto_discovery_url">{{.i18n.Tr "admin.auths.openIdConnectAutoDiscoveryURL"}}</label>
|
<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}}">
|
<input id="open_id_connect_auto_discovery_url" name="open_id_connect_auto_discovery_url" value="{{.open_id_connect_auto_discovery_url}}">
|
||||||
</div>
|
</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="oauth2_use_custom_url inline field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
|
|
Reference in a new issue