-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for FIDO U2F #3971
Merged
Merged
Add support for FIDO U2F #3971
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
008a62e
Add support for U2F
jonasfranz a72944b
Add vendor library
jonasfranz 18b3f09
Minor improvements
jonasfranz acf6728
Add U2F support for Firefox, Chrome (Android) by introducing a custom…
jonasfranz 1966eb6
Merge branch 'master' into u2f
jonasfranz bf0aae7
Merge branch 'master' into u2f
jonasfranz 60f0ae7
Add U2F login page to OAuth
jonasfranz 0dcda4d
Merge remote-tracking branch 'onion/u2f' into u2f
jonasfranz bc68bef
Merge branch 'master' into u2f
jonasfranz 2c8120d
Move U2F user settings to a separate file
jonasfranz 77a4d04
Add unit tests for u2f model
jonasfranz bd47db7
Fix problems caused by refactoring
jonasfranz 506fbde
Add U2F documentation
jonasfranz 7cc9eb4
Merge branch 'master' into u2f
lafriks 20a817c
Merge branch 'master' into u2f
jonasfranz f8e44a5
Remove not needed console.log-s
jonasfranz 0270ce6
Merge remote-tracking branch 'onion/u2f' into u2f
jonasfranz 66552e7
Add default values to app.ini.sample
jonasfranz 378b921
Merge branch 'master' into u2f
jonasfranz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -288,7 +288,7 @@ RESET_PASSWD_CODE_LIVE_MINUTES = 180 | |
REGISTER_EMAIL_CONFIRM = false | ||
; Disallow registration, only allow admins to create accounts. | ||
DISABLE_REGISTRATION = false | ||
; Allow registration only using third part services, it works only when DISABLE_REGISTRATION is false | ||
; Allow registration only using third part services, it works only when DISABLE_REGISTRATION is false | ||
ALLOW_ONLY_EXTERNAL_REGISTRATION = false | ||
; User must sign in to view anything. | ||
REQUIRE_SIGNIN_VIEW = false | ||
|
@@ -570,6 +570,14 @@ MAX_RESPONSE_ITEMS = 50 | |
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR | ||
NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어 | ||
|
||
[U2F] | ||
; Two Factor authentication with security keys | ||
; https://developers.yubico.com/U2F/App_ID.html | ||
APP_ID = https://example.com | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
; Comma seperated list of truisted facets | ||
TRUSTED_FACETS = https://localhost:3000,https://192.168.178.18:3000 | ||
|
||
|
||
; Used for datetimepicker | ||
[i18n.datelang] | ||
en-US = en | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
- | ||
id: 1 | ||
name: "U2F Key" | ||
user_id: 1 | ||
counter: 0 | ||
created_unix: 946684800 | ||
updated_unix: 946684800 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package migrations | ||
|
||
import ( | ||
"code.gitea.io/gitea/modules/util" | ||
"github.com/go-xorm/xorm" | ||
) | ||
|
||
func addU2FReg(x *xorm.Engine) error { | ||
type U2FRegistration struct { | ||
ID int64 `xorm:"pk autoincr"` | ||
Name string | ||
UserID int64 `xorm:"INDEX"` | ||
Raw []byte | ||
Counter uint32 | ||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | ||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | ||
} | ||
return x.Sync2(&U2FRegistration{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright 2018 The Gitea Authors. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package models | ||
|
||
import ( | ||
"code.gitea.io/gitea/modules/log" | ||
"code.gitea.io/gitea/modules/util" | ||
|
||
"github.com/tstranex/u2f" | ||
) | ||
|
||
// U2FRegistration represents the registration data and counter of a security key | ||
type U2FRegistration struct { | ||
ID int64 `xorm:"pk autoincr"` | ||
Name string | ||
UserID int64 `xorm:"INDEX"` | ||
Raw []byte | ||
Counter uint32 | ||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | ||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | ||
} | ||
|
||
// TableName returns a better table name for U2FRegistration | ||
func (reg U2FRegistration) TableName() string { | ||
return "u2f_registration" | ||
} | ||
|
||
// Parse will convert the db entry U2FRegistration to an u2f.Registration struct | ||
func (reg *U2FRegistration) Parse() (*u2f.Registration, error) { | ||
r := new(u2f.Registration) | ||
return r, r.UnmarshalBinary(reg.Raw) | ||
} | ||
|
||
func (reg *U2FRegistration) updateCounter(e Engine) error { | ||
_, err := e.ID(reg.ID).Cols("counter").Update(reg) | ||
return err | ||
} | ||
|
||
// UpdateCounter will update the database value of counter | ||
func (reg *U2FRegistration) UpdateCounter() error { | ||
return reg.updateCounter(x) | ||
} | ||
|
||
// U2FRegistrationList is a list of *U2FRegistration | ||
type U2FRegistrationList []*U2FRegistration | ||
|
||
// ToRegistrations will convert all U2FRegistrations to u2f.Registrations | ||
func (list U2FRegistrationList) ToRegistrations() []u2f.Registration { | ||
regs := make([]u2f.Registration, len(list)) | ||
for _, reg := range list { | ||
r, err := reg.Parse() | ||
if err != nil { | ||
log.Fatal(4, "parsing u2f registration: %v", err) | ||
continue | ||
} | ||
regs = append(regs, *r) | ||
} | ||
|
||
return regs | ||
} | ||
|
||
func getU2FRegistrationsByUID(e Engine, uid int64) (U2FRegistrationList, error) { | ||
regs := make(U2FRegistrationList, 0) | ||
return regs, e.Where("user_id = ?", uid).Find(®s) | ||
} | ||
|
||
// GetU2FRegistrationByID returns U2F registration by id | ||
func GetU2FRegistrationByID(id int64) (*U2FRegistration, error) { | ||
return getU2FRegistrationByID(x, id) | ||
} | ||
|
||
func getU2FRegistrationByID(e Engine, id int64) (*U2FRegistration, error) { | ||
reg := new(U2FRegistration) | ||
if found, err := e.ID(id).Get(reg); err != nil { | ||
return nil, err | ||
} else if !found { | ||
return nil, ErrU2FRegistrationNotExist{ID: id} | ||
} | ||
return reg, nil | ||
} | ||
|
||
// GetU2FRegistrationsByUID returns all U2F registrations of the given user | ||
func GetU2FRegistrationsByUID(uid int64) (U2FRegistrationList, error) { | ||
return getU2FRegistrationsByUID(x, uid) | ||
} | ||
|
||
func createRegistration(e Engine, user *User, name string, reg *u2f.Registration) (*U2FRegistration, error) { | ||
raw, err := reg.MarshalBinary() | ||
if err != nil { | ||
return nil, err | ||
} | ||
r := &U2FRegistration{ | ||
UserID: user.ID, | ||
Name: name, | ||
Counter: 0, | ||
Raw: raw, | ||
} | ||
_, err = e.InsertOne(r) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return r, nil | ||
} | ||
|
||
// CreateRegistration will create a new U2FRegistration from the given Registration | ||
func CreateRegistration(user *User, name string, reg *u2f.Registration) (*U2FRegistration, error) { | ||
return createRegistration(x, user, name, reg) | ||
} | ||
|
||
// DeleteRegistration will delete U2FRegistration | ||
func DeleteRegistration(reg *U2FRegistration) error { | ||
return deleteRegistration(x, reg) | ||
} | ||
|
||
func deleteRegistration(e Engine, reg *U2FRegistration) error { | ||
_, err := e.Delete(reg) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package models | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/tstranex/u2f" | ||
) | ||
|
||
func TestGetU2FRegistrationByID(t *testing.T) { | ||
assert.NoError(t, PrepareTestDatabase()) | ||
|
||
res, err := GetU2FRegistrationByID(1) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "U2F Key", res.Name) | ||
|
||
_, err = GetU2FRegistrationByID(342432) | ||
assert.Error(t, err) | ||
assert.True(t, IsErrU2FRegistrationNotExist(err)) | ||
} | ||
|
||
func TestGetU2FRegistrationsByUID(t *testing.T) { | ||
assert.NoError(t, PrepareTestDatabase()) | ||
|
||
res, err := GetU2FRegistrationsByUID(1) | ||
assert.NoError(t, err) | ||
assert.Len(t, res, 1) | ||
assert.Equal(t, "U2F Key", res[0].Name) | ||
} | ||
|
||
func TestU2FRegistration_TableName(t *testing.T) { | ||
assert.Equal(t, "u2f_registration", U2FRegistration{}.TableName()) | ||
} | ||
|
||
func TestU2FRegistration_UpdateCounter(t *testing.T) { | ||
assert.NoError(t, PrepareTestDatabase()) | ||
reg := AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration) | ||
reg.Counter = 1 | ||
assert.NoError(t, reg.UpdateCounter()) | ||
AssertExistsIf(t, true, &U2FRegistration{ID: 1, Counter: 1}) | ||
} | ||
|
||
func TestCreateRegistration(t *testing.T) { | ||
assert.NoError(t, PrepareTestDatabase()) | ||
user := AssertExistsAndLoadBean(t, &User{ID: 1}).(*User) | ||
|
||
res, err := CreateRegistration(user, "U2F Created Key", &u2f.Registration{Raw: []byte("Test")}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "U2F Created Key", res.Name) | ||
assert.Equal(t, []byte("Test"), res.Raw) | ||
|
||
AssertExistsIf(t, true, &U2FRegistration{Name: "U2F Created Key", UserID: user.ID}) | ||
} | ||
|
||
func TestDeleteRegistration(t *testing.T) { | ||
assert.NoError(t, PrepareTestDatabase()) | ||
reg := AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration) | ||
|
||
assert.NoError(t, DeleteRegistration(reg)) | ||
AssertNotExistsBean(t, &U2FRegistration{ID: 1}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a U2F section to the "Config Cheatsheet" page in the docs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@techknowlogick done