mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-08 22:13:26 +09:00
fix(auth): set WebAuthn user verification per request (#38805)
Registration omitted `userVerification`, so Chromium raised the credential to credProtect level 3 and the authenticator then hid it from the second-factor login, which asked for `discouraged`. Registration and each login now set their own value, with `preferred` on the second factor so credentials already registered at level 3 keep working without re-enrollment. Also add relevant e2e test coverage for webauthn, one test chromium only because Firefox lacks the APIs needed. Fixes https://github.com/go-gitea/gitea/issues/33531 Fixes https://github.com/go-gitea/gitea/issues/36019 Fixes https://github.com/go-gitea/gitea/issues/38139
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
auth_model "gitea.dev/models/auth"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/auth/openid"
|
||||
"gitea.dev/modules/log"
|
||||
@@ -26,6 +27,36 @@ const (
|
||||
tplSignUpOID templates.TplName = "user/auth/signup_openid_register"
|
||||
)
|
||||
|
||||
// the OpenID is attached only after the second factor passed, so a stolen password cannot leave one behind
|
||||
func openIDRequireTwoFactor(ctx *context.Context, u *user_model.User, remember bool, pendingURI string) {
|
||||
hasTwoFactor, err := auth_model.HasTwoFactorOrWebAuthn(ctx, u.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("HasTwoFactorOrWebAuthn", err)
|
||||
return
|
||||
}
|
||||
if !hasTwoFactor {
|
||||
return
|
||||
}
|
||||
handleTwoFactorRequired(ctx, u, remember, map[string]any{"openidPendingURI": pendingURI})
|
||||
}
|
||||
|
||||
func openIDConnectFromContext(ctx *context.Context, u *user_model.User) error {
|
||||
uri, _ := ctx.Session.Get("openidPendingURI").(string)
|
||||
if uri == "" {
|
||||
return nil
|
||||
}
|
||||
if err := ctx.Session.Delete("openidPendingURI"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := user_model.AddUserOpenID(ctx, &user_model.UserOpenID{UID: u.ID, URI: uri}); err != nil {
|
||||
if !user_model.IsErrOpenIDAlreadyUsed(err) {
|
||||
return err
|
||||
}
|
||||
ctx.Flash.Error(ctx.Tr("form.openid_been_used", uri))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SignInOpenID render sign in page
|
||||
func SignInOpenID(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("sign_in")
|
||||
@@ -154,6 +185,10 @@ func signInOpenIDVerify(ctx *context.Context) {
|
||||
log.Trace("User exists, logging in")
|
||||
remember, _ := ctx.Session.Get("openid_signin_remember").(bool)
|
||||
log.Trace("Session stored openid-remember: %t", remember)
|
||||
openIDRequireTwoFactor(ctx, u, remember, "")
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
handleSignIn(ctx, u, remember)
|
||||
return
|
||||
}
|
||||
@@ -270,7 +305,12 @@ func ConnectOpenIDPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// add OpenID for the user
|
||||
remember, _ := ctx.Session.Get("openid_signin_remember").(bool)
|
||||
openIDRequireTwoFactor(ctx, u, remember, oid)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
userOID := &user_model.UserOpenID{UID: u.ID, URI: oid}
|
||||
if err := user_model.AddUserOpenID(ctx, userOID); err != nil {
|
||||
if user_model.IsErrOpenIDAlreadyUsed(err) {
|
||||
@@ -282,9 +322,6 @@ func ConnectOpenIDPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.add_openid_success"))
|
||||
|
||||
remember, _ := ctx.Session.Get("openid_signin_remember").(bool)
|
||||
log.Trace("Session stored openid-remember: %t", remember)
|
||||
handleSignIn(ctx, u, remember)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user