Skip to content

Commit d03e7fd

Browse files
wxiaoguangyp05327
andauthored
Support disable passkey auth (#33348) (#33819)
* Backport #33348 * Backport #33820 --------- Co-authored-by: yp05327 <[email protected]>
1 parent 92f2d90 commit d03e7fd

File tree

8 files changed

+53
-6
lines changed

8 files changed

+53
-6
lines changed

Diff for: custom/conf/app.example.ini

+4-1
Original file line numberDiff line numberDiff line change
@@ -784,10 +784,13 @@ LEVEL = Info
784784
;; Please note that setting this to false will not disable OAuth Basic or Basic authentication using a token
785785
;ENABLE_BASIC_AUTHENTICATION = true
786786
;;
787-
;; Show the password sign-in form (for password-based login), otherwise, only show OAuth2 login methods.
787+
;; Show the password sign-in form (for password-based login), otherwise, only show OAuth2 or passkey login methods if they are enabled.
788788
;; If you set it to false, maybe it also needs to set ENABLE_BASIC_AUTHENTICATION to false to completely disable password-based authentication.
789789
;ENABLE_PASSWORD_SIGNIN_FORM = true
790790
;;
791+
;; Allow users to sign-in with a passkey
792+
;ENABLE_PASSKEY_AUTHENTICATION = true
793+
;;
791794
;; More detail: https://github.com/gogits/gogs/issues/165
792795
;ENABLE_REVERSE_PROXY_AUTHENTICATION = false
793796
; Enable this to allow reverse proxy authentication for API requests, the reverse proxy is responsible for ensuring that no CSRF is possible.

Diff for: modules/setting/service.go

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ var Service = struct {
4646
RequireSignInView bool
4747
EnableNotifyMail bool
4848
EnableBasicAuth bool
49+
EnablePasskeyAuth bool
4950
EnableReverseProxyAuth bool
5051
EnableReverseProxyAuthAPI bool
5152
EnableReverseProxyAutoRegister bool
@@ -161,6 +162,7 @@ func loadServiceFrom(rootCfg ConfigProvider) {
161162
Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
162163
Service.EnableBasicAuth = sec.Key("ENABLE_BASIC_AUTHENTICATION").MustBool(true)
163164
Service.EnablePasswordSignInForm = sec.Key("ENABLE_PASSWORD_SIGNIN_FORM").MustBool(true)
165+
Service.EnablePasskeyAuth = sec.Key("ENABLE_PASSKEY_AUTHENTICATION").MustBool(true)
164166
Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
165167
Service.EnableReverseProxyAuthAPI = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION_API").MustBool()
166168
Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()

Diff for: routers/web/auth/auth.go

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ func prepareSignInPageData(ctx *context.Context) {
169169
ctx.Data["PageIsLogin"] = true
170170
ctx.Data["EnableSSPI"] = auth.IsSSPIEnabled(ctx)
171171
ctx.Data["EnablePasswordSignInForm"] = setting.Service.EnablePasswordSignInForm
172+
ctx.Data["EnablePasskeyAuth"] = setting.Service.EnablePasskeyAuth
172173

173174
if setting.Service.EnableCaptcha && setting.Service.RequireCaptchaForLogin {
174175
context.SetCaptchaData(ctx)

Diff for: routers/web/auth/linkaccount.go

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func LinkAccount(ctx *context.Context) {
4646
ctx.Data["AllowOnlyInternalRegistration"] = setting.Service.AllowOnlyInternalRegistration
4747
ctx.Data["EnablePasswordSignInForm"] = setting.Service.EnablePasswordSignInForm
4848
ctx.Data["ShowRegistrationButton"] = false
49+
ctx.Data["EnablePasskeyAuth"] = setting.Service.EnablePasskeyAuth
4950

5051
// use this to set the right link into the signIn and signUp templates in the link_account template
5152
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
@@ -145,6 +146,7 @@ func LinkAccountPostSignIn(ctx *context.Context) {
145146
ctx.Data["AllowOnlyInternalRegistration"] = setting.Service.AllowOnlyInternalRegistration
146147
ctx.Data["EnablePasswordSignInForm"] = setting.Service.EnablePasswordSignInForm
147148
ctx.Data["ShowRegistrationButton"] = false
149+
ctx.Data["EnablePasskeyAuth"] = setting.Service.EnablePasskeyAuth
148150

149151
// use this to set the right link into the signIn and signUp templates in the link_account template
150152
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
@@ -235,6 +237,7 @@ func LinkAccountPostRegister(ctx *context.Context) {
235237
ctx.Data["AllowOnlyInternalRegistration"] = setting.Service.AllowOnlyInternalRegistration
236238
ctx.Data["EnablePasswordSignInForm"] = setting.Service.EnablePasswordSignInForm
237239
ctx.Data["ShowRegistrationButton"] = false
240+
ctx.Data["EnablePasskeyAuth"] = setting.Service.EnablePasskeyAuth
238241

239242
// use this to set the right link into the signIn and signUp templates in the link_account template
240243
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"

Diff for: routers/web/auth/webauthn.go

+10
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ func WebAuthn(ctx *context.Context) {
5050

5151
// WebAuthnPasskeyAssertion submits a WebAuthn challenge for the passkey login to the browser
5252
func WebAuthnPasskeyAssertion(ctx *context.Context) {
53+
if !setting.Service.EnablePasskeyAuth {
54+
ctx.Error(http.StatusForbidden)
55+
return
56+
}
57+
5358
assertion, sessionData, err := wa.WebAuthn.BeginDiscoverableLogin()
5459
if err != nil {
5560
ctx.ServerError("webauthn.BeginDiscoverableLogin", err)
@@ -66,6 +71,11 @@ func WebAuthnPasskeyAssertion(ctx *context.Context) {
6671

6772
// WebAuthnPasskeyLogin handles the WebAuthn login process using a Passkey
6873
func WebAuthnPasskeyLogin(ctx *context.Context) {
74+
if !setting.Service.EnablePasskeyAuth {
75+
ctx.Error(http.StatusForbidden)
76+
return
77+
}
78+
6979
sessionData, okData := ctx.Session.Get("webauthnPasskeyAssertion").(*webauthn.SessionData)
7080
if !okData || sessionData == nil {
7181
ctx.ServerError("ctx.Session.Get", errors.New("not in WebAuthn session"))

Diff for: templates/user/auth/signin_inner.tmpl

+4-3
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@
6060
</div>
6161

6262
<div class="ui container fluid">
63-
{{template "user/auth/webauthn_error" .}}
64-
6563
<div class="ui attached segment header top tw-max-w-2xl tw-m-auto tw-flex tw-flex-col tw-items-center">
66-
<a class="signin-passkey">{{ctx.Locale.Tr "auth.signin_passkey"}}</a>
64+
{{if .EnablePasskeyAuth}}
65+
{{template "user/auth/webauthn_error" .}}
66+
<a class="signin-passkey">{{ctx.Locale.Tr "auth.signin_passkey"}}</a>
67+
{{end}}
6768

6869
{{if .ShowRegistrationButton}}
6970
<div class="field">

Diff for: tests/integration/signin_test.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func TestSigninWithRememberMe(t *testing.T) {
9696
session.MakeRequest(t, req, http.StatusOK)
9797
}
9898

99-
func TestEnablePasswordSignInForm(t *testing.T) {
99+
func TestEnablePasswordSignInFormAndEnablePasskeyAuth(t *testing.T) {
100100
defer tests.PrepareTestEnv(t)()
101101

102102
mockLinkAccount := func(ctx *context.Context) {
@@ -139,4 +139,22 @@ func TestEnablePasswordSignInForm(t *testing.T) {
139139
resp = MakeRequest(t, req, http.StatusOK)
140140
NewHTMLParser(t, resp.Body).AssertElement(t, "form[action='/user/link_account_signin']", true)
141141
})
142+
143+
t.Run("EnablePasskeyAuth=false", func(t *testing.T) {
144+
defer tests.PrintCurrentTest(t)()
145+
defer test.MockVariableValue(&setting.Service.EnablePasskeyAuth, false)()
146+
147+
req := NewRequest(t, "GET", "/user/login")
148+
resp := MakeRequest(t, req, http.StatusOK)
149+
NewHTMLParser(t, resp.Body).AssertElement(t, ".signin-passkey", false)
150+
})
151+
152+
t.Run("EnablePasskeyAuth=true", func(t *testing.T) {
153+
defer tests.PrintCurrentTest(t)()
154+
defer test.MockVariableValue(&setting.Service.EnablePasskeyAuth, true)()
155+
156+
req := NewRequest(t, "GET", "/user/login")
157+
resp := MakeRequest(t, req, http.StatusOK)
158+
NewHTMLParser(t, resp.Body).AssertElement(t, ".signin-passkey", true)
159+
})
142160
}

Diff for: web_src/js/features/user-auth-webauthn.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {encodeURLEncodedBase64, decodeURLEncodedBase64} from '../utils.ts';
2-
import {showElem} from '../utils/dom.ts';
2+
import {hideElem, showElem} from '../utils/dom.ts';
33
import {GET, POST} from '../modules/fetch.ts';
44

55
const {appSubUrl} = window.config;
@@ -11,6 +11,15 @@ export async function initUserAuthWebAuthn() {
1111
return;
1212
}
1313

14+
if (window.location.protocol === 'http:') {
15+
// webauthn is only supported on secure contexts
16+
const isLocalhost = ['localhost', '127.0.0.1'].includes(window.location.hostname);
17+
if (!isLocalhost) {
18+
hideElem(elSignInPasskeyBtn);
19+
return;
20+
}
21+
}
22+
1423
if (!detectWebAuthnSupport()) {
1524
return;
1625
}

0 commit comments

Comments
 (0)