Allow U2F 2FA without TOTP (#11573)

This change enables the usage of U2F without being forced to enroll an TOTP authenticator.
The `/user/auth/u2f` has been changed to hide the "use TOTP instead" bar if TOTP is not enrolled.

Fixes #5410
Fixes #17495
This commit is contained in:
Kamil Domański 2021-11-08 23:47:19 +01:00 committed by GitHub
parent a3f9e9234c
commit 021df29623
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 100 additions and 57 deletions

View file

@ -1,7 +1,7 @@
-
id: 1
name: "U2F Key"
user_id: 1
user_id: 32
counter: 0
created_unix: 946684800
updated_unix: 946684800

View file

@ -542,3 +542,19 @@
avatar_email: user31@example.com
num_repos: 0
is_active: true
-
id: 32
lower_name: user32
name: user32
full_name: User 32 (U2F test)
email: user32@example.com
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
type: 0 # individual
salt: ZogKvWdyEx
is_admin: false
is_restricted: false
avatar: avatar32
avatar_email: user30@example.com
num_repos: 0
is_active: true

View file

@ -136,6 +136,12 @@ func GetTwoFactorByUID(uid int64) (*TwoFactor, error) {
return twofa, nil
}
// HasTwoFactorByUID returns the two-factor authentication token associated with
// the user, if any.
func HasTwoFactorByUID(uid int64) (bool, error) {
return db.GetEngine(db.DefaultContext).Where("uid=?", uid).Exist(&TwoFactor{})
}
// DeleteTwoFactorByID deletes two-factor authentication token by given ID.
func DeleteTwoFactorByID(id, userID int64) error {
cnt, err := db.GetEngine(db.DefaultContext).ID(id).Delete(&TwoFactor{

View file

@ -115,6 +115,11 @@ func GetU2FRegistrationsByUID(uid int64) (U2FRegistrationList, error) {
return getU2FRegistrationsByUID(db.GetEngine(db.DefaultContext), uid)
}
// HasU2FRegistrationsByUID returns whether a given user has U2F registrations
func HasU2FRegistrationsByUID(uid int64) (bool, error) {
return db.GetEngine(db.DefaultContext).Where("user_id = ?", uid).Exist(&U2FRegistration{})
}
func createRegistration(e db.Engine, userID int64, name string, reg *u2f.Registration) (*U2FRegistration, error) {
raw, err := reg.MarshalBinary()
if err != nil {

View file

@ -29,7 +29,7 @@ func TestGetU2FRegistrationByID(t *testing.T) {
func TestGetU2FRegistrationsByUID(t *testing.T) {
assert.NoError(t, db.PrepareTestDatabase())
res, err := GetU2FRegistrationsByUID(1)
res, err := GetU2FRegistrationsByUID(32)
assert.NoError(t, err)
assert.Len(t, res, 1)

View file

@ -147,13 +147,13 @@ func TestSearchUsers(t *testing.T) {
}
testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}},
[]int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30})
[]int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32})
testUserSuccess(&SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolFalse},
[]int64{9})
testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue},
[]int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 28, 29, 30})
[]int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 28, 29, 30, 32})
testUserSuccess(&SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue},
[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18})