mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-27 21:03:56 +01:00
Merge branch 'main' into remove_vendor_doc
This commit is contained in:
commit
c91dcb94ba
14 changed files with 137 additions and 76 deletions
13
Makefile
13
Makefile
|
@ -292,7 +292,7 @@ fmt-check:
|
||||||
checks: checks-frontend checks-backend
|
checks: checks-frontend checks-backend
|
||||||
|
|
||||||
.PHONY: checks-frontend
|
.PHONY: checks-frontend
|
||||||
checks-frontend: svg-check
|
checks-frontend: lockfile-check svg-check
|
||||||
|
|
||||||
.PHONY: checks-backend
|
.PHONY: checks-backend
|
||||||
checks-backend: test-vendor swagger-check swagger-validate
|
checks-backend: test-vendor swagger-check swagger-validate
|
||||||
|
@ -700,6 +700,17 @@ svg-check: svg
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
.PHONY: lockfile-check
|
||||||
|
lockfile-check:
|
||||||
|
npm install --package-lock-only
|
||||||
|
@diff=$$(git diff package-lock.json); \
|
||||||
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "package-lock.json is inconsistent with package.json"; \
|
||||||
|
echo "Please run 'npm install --package-lock-only' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: update-translations
|
.PHONY: update-translations
|
||||||
update-translations:
|
update-translations:
|
||||||
mkdir -p ./translations
|
mkdir -p ./translations
|
||||||
|
|
|
@ -128,6 +128,7 @@ This error indicates nginx is configured to restrict the file upload size.
|
||||||
|
|
||||||
In your nginx config file containing your Gitea proxy directive, find the `location { ... }` block for Gitea and add the line
|
In your nginx config file containing your Gitea proxy directive, find the `location { ... }` block for Gitea and add the line
|
||||||
`client_max_body_size 16M;` to set this limit to 16 megabytes or any other number of choice.
|
`client_max_body_size 16M;` to set this limit to 16 megabytes or any other number of choice.
|
||||||
|
If you use Git LFS, this will also limit the size of the largest file you will be able to push.
|
||||||
|
|
||||||
|
|
||||||
## Apache HTTPD
|
## Apache HTTPD
|
||||||
|
|
|
@ -6,7 +6,7 @@ package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base32"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ type WebAuthnCredentialList []*WebAuthnCredential
|
||||||
func (list WebAuthnCredentialList) ToCredentials() []webauthn.Credential {
|
func (list WebAuthnCredentialList) ToCredentials() []webauthn.Credential {
|
||||||
creds := make([]webauthn.Credential, 0, len(list))
|
creds := make([]webauthn.Credential, 0, len(list))
|
||||||
for _, cred := range list {
|
for _, cred := range list {
|
||||||
credID, _ := base64.RawStdEncoding.DecodeString(cred.CredentialID)
|
credID, _ := base32.HexEncoding.DecodeString(cred.CredentialID)
|
||||||
creds = append(creds, webauthn.Credential{
|
creds = append(creds, webauthn.Credential{
|
||||||
ID: credID,
|
ID: credID,
|
||||||
PublicKey: cred.PublicKey,
|
PublicKey: cred.PublicKey,
|
||||||
|
@ -164,13 +164,13 @@ func HasWebAuthnRegistrationsByUID(uid int64) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWebAuthnCredentialByCredID returns WebAuthn credential by credential ID
|
// GetWebAuthnCredentialByCredID returns WebAuthn credential by credential ID
|
||||||
func GetWebAuthnCredentialByCredID(credID string) (*WebAuthnCredential, error) {
|
func GetWebAuthnCredentialByCredID(userID int64, credID string) (*WebAuthnCredential, error) {
|
||||||
return getWebAuthnCredentialByCredID(db.DefaultContext, credID)
|
return getWebAuthnCredentialByCredID(db.DefaultContext, userID, credID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWebAuthnCredentialByCredID(ctx context.Context, credID string) (*WebAuthnCredential, error) {
|
func getWebAuthnCredentialByCredID(ctx context.Context, userID int64, credID string) (*WebAuthnCredential, error) {
|
||||||
cred := new(WebAuthnCredential)
|
cred := new(WebAuthnCredential)
|
||||||
if found, err := db.GetEngine(ctx).Where("credential_id = ?", credID).Get(cred); err != nil {
|
if found, err := db.GetEngine(ctx).Where("user_id = ? AND credential_id = ?", userID, credID).Get(cred); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !found {
|
} else if !found {
|
||||||
return nil, ErrWebAuthnCredentialNotExist{CredentialID: credID}
|
return nil, ErrWebAuthnCredentialNotExist{CredentialID: credID}
|
||||||
|
@ -187,7 +187,7 @@ func createCredential(ctx context.Context, userID int64, name string, cred *weba
|
||||||
c := &WebAuthnCredential{
|
c := &WebAuthnCredential{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Name: name,
|
Name: name,
|
||||||
CredentialID: base64.RawStdEncoding.EncodeToString(cred.ID),
|
CredentialID: base32.HexEncoding.EncodeToString(cred.ID),
|
||||||
PublicKey: cred.PublicKey,
|
PublicKey: cred.PublicKey,
|
||||||
AttestationType: cred.AttestationType,
|
AttestationType: cred.AttestationType,
|
||||||
AAGUID: cred.Authenticator.AAGUID,
|
AAGUID: cred.Authenticator.AAGUID,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base32"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -61,7 +61,7 @@ func TestCreateCredential(t *testing.T) {
|
||||||
res, err := CreateCredential(1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")})
|
res, err := CreateCredential(1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "WebAuthn Created Credential", res.Name)
|
assert.Equal(t, "WebAuthn Created Credential", res.Name)
|
||||||
bs, err := base64.RawStdEncoding.DecodeString(res.CredentialID)
|
bs, err := base32.HexEncoding.DecodeString(res.CredentialID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []byte("Test"), bs)
|
assert.Equal(t, []byte("Test"), bs)
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,8 @@ var migrations = []Migration{
|
||||||
NewMigration("Add authorize column to team_unit table", addAuthorizeColForTeamUnit),
|
NewMigration("Add authorize column to team_unit table", addAuthorizeColForTeamUnit),
|
||||||
// v207 -> v208
|
// v207 -> v208
|
||||||
NewMigration("Add webauthn table and migrate u2f data to webauthn", addWebAuthnCred),
|
NewMigration("Add webauthn table and migrate u2f data to webauthn", addWebAuthnCred),
|
||||||
|
// v208 -> v209
|
||||||
|
NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive", useBase32HexForCredIDInWebAuthnCredential),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentDBVersion returns the current db version
|
// GetCurrentDBVersion returns the current db version
|
||||||
|
|
51
models/migrations/v208.go
Normal file
51
models/migrations/v208.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright 2021 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 migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base32"
|
||||||
|
"encoding/base64"
|
||||||
|
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func useBase32HexForCredIDInWebAuthnCredential(x *xorm.Engine) error {
|
||||||
|
|
||||||
|
// Create webauthnCredential table
|
||||||
|
type webauthnCredential struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
CredentialID string `xorm:"INDEX"`
|
||||||
|
}
|
||||||
|
if err := x.Sync2(&webauthnCredential{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var start int
|
||||||
|
regs := make([]*webauthnCredential, 0, 50)
|
||||||
|
for {
|
||||||
|
err := x.OrderBy("id").Limit(50, start).Find(®s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, reg := range regs {
|
||||||
|
credID, _ := base64.RawStdEncoding.DecodeString(reg.CredentialID)
|
||||||
|
reg.CredentialID = base32.HexEncoding.EncodeToString(credID)
|
||||||
|
|
||||||
|
_, err := x.Update(reg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(regs) < 50 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
start += 50
|
||||||
|
regs = regs[:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -748,10 +748,9 @@ passcode_invalid = The passcode is incorrect. Try again.
|
||||||
twofa_enrolled = Your account has been enrolled into two-factor authentication. Store your scratch token (%s) in a safe place as it is only shown once!
|
twofa_enrolled = Your account has been enrolled into two-factor authentication. Store your scratch token (%s) in a safe place as it is only shown once!
|
||||||
twofa_failed_get_secret = Failed to get secret.
|
twofa_failed_get_secret = Failed to get secret.
|
||||||
|
|
||||||
webauthn_desc = Security keys are hardware devices containing cryptographic keys. They can be used for two-factor authentication. Security keys must support the <a rel="noreferrer" href="https://w3c.github.io/webauthn/#webauthn-authenticator">WebAuthn Authenticator</a> standard.
|
webauthn_desc = Security keys are hardware devices containing cryptographic keys. They can be used for two-factor authentication. Security keys must support the <a rel="noreferrer" target="_blank" href="https://w3c.github.io/webauthn/#webauthn-authenticator">WebAuthn Authenticator</a> standard.
|
||||||
webauthn_register_key = Add Security Key
|
webauthn_register_key = Add Security Key
|
||||||
webauthn_nickname = Nickname
|
webauthn_nickname = Nickname
|
||||||
webauthn_press_button = Press the button on your security key to register it.
|
|
||||||
webauthn_delete_key = Remove Security Key
|
webauthn_delete_key = Remove Security Key
|
||||||
webauthn_delete_key_desc = If you remove a security key you can no longer sign in with it. Continue?
|
webauthn_delete_key_desc = If you remove a security key you can no longer sign in with it. Continue?
|
||||||
|
|
||||||
|
|
71
package-lock.json
generated
71
package-lock.json
generated
|
@ -4,6 +4,7 @@
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "gitea",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@claviska/jquery-minicolors": "2.3.6",
|
"@claviska/jquery-minicolors": "2.3.6",
|
||||||
|
@ -12,7 +13,7 @@
|
||||||
"codemirror": "5.64.0",
|
"codemirror": "5.64.0",
|
||||||
"css-loader": "6.5.1",
|
"css-loader": "6.5.1",
|
||||||
"dropzone": "6.0.0-beta.2",
|
"dropzone": "6.0.0-beta.2",
|
||||||
"easymde": "2.15.0",
|
"easymde": "2.16.1",
|
||||||
"esbuild-loader": "2.16.0",
|
"esbuild-loader": "2.16.0",
|
||||||
"escape-goat": "4.0.0",
|
"escape-goat": "4.0.0",
|
||||||
"fast-glob": "3.2.7",
|
"fast-glob": "3.2.7",
|
||||||
|
@ -1305,9 +1306,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/codemirror": {
|
"node_modules/@types/codemirror": {
|
||||||
"version": "0.0.109",
|
"version": "5.60.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz",
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||||
"integrity": "sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg==",
|
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/tern": "*"
|
"@types/tern": "*"
|
||||||
}
|
}
|
||||||
|
@ -1380,9 +1381,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/marked": {
|
"node_modules/@types/marked": {
|
||||||
"version": "2.0.5",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.1.tgz",
|
||||||
"integrity": "sha512-shRZ7XnYFD/8n8zSjKvFdto1QNSf4tONZIlNEZGrJe8GsOE8DL/hG1Hbl8gZlfLnjS7+f5tZGIaTgfpyW38h4w=="
|
"integrity": "sha512-ZigEmCWdNUU7IjZEuQ/iaimYdDHWHfTe3kg8ORfKjyGYd9RWumPoOJRQXB0bO+XLkNwzCthW3wUIQtANaEZ1ag=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/minimist": {
|
"node_modules/@types/minimist": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
|
@ -3780,15 +3781,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/easymde": {
|
"node_modules/easymde": {
|
||||||
"version": "2.15.0",
|
"version": "2.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/easymde/-/easymde-2.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/easymde/-/easymde-2.16.1.tgz",
|
||||||
"integrity": "sha512-9jMRIVvKt1d0UjRN45yotUYECAM4xvw0TTAQw8sYDONP++keWJVnd8Xrn+V+vQEN/v9/X0SWEoo1rFSgCooGpw==",
|
"integrity": "sha512-FihYgjRsKfhGNk89SHSqxKLC4aJ1kfybPWW6iAmtb5GnXu+tnFPSzSaGBmk1RRlCuhFSjhF0SnIMGVPjEzkr6g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/codemirror": "0.0.109",
|
"@types/codemirror": "^5.60.4",
|
||||||
"@types/marked": "^2.0.2",
|
"@types/marked": "^4.0.1",
|
||||||
"codemirror": "^5.61.0",
|
"codemirror": "^5.63.1",
|
||||||
"codemirror-spell-checker": "1.1.2",
|
"codemirror-spell-checker": "1.1.2",
|
||||||
"marked": "^2.0.3"
|
"marked": "^4.0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/editorconfig-checker": {
|
"node_modules/editorconfig-checker": {
|
||||||
|
@ -7356,14 +7357,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked": {
|
"node_modules/marked": {
|
||||||
"version": "2.1.3",
|
"version": "4.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz",
|
||||||
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==",
|
"integrity": "sha512-+QvuFj0nGgO970fySghXGmuw+Fd0gD2x3+MqCWLIPf5oxdv1Ka6b2q+z9RP01P/IaKPMEramy+7cNy/Lw8c3hw==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"marked": "bin/marked"
|
"marked": "bin/marked.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mathml-tag-names": {
|
"node_modules/mathml-tag-names": {
|
||||||
|
@ -11526,9 +11527,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/codemirror": {
|
"@types/codemirror": {
|
||||||
"version": "0.0.109",
|
"version": "5.60.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz",
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||||
"integrity": "sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg==",
|
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/tern": "*"
|
"@types/tern": "*"
|
||||||
}
|
}
|
||||||
|
@ -11601,9 +11602,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/marked": {
|
"@types/marked": {
|
||||||
"version": "2.0.5",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.1.tgz",
|
||||||
"integrity": "sha512-shRZ7XnYFD/8n8zSjKvFdto1QNSf4tONZIlNEZGrJe8GsOE8DL/hG1Hbl8gZlfLnjS7+f5tZGIaTgfpyW38h4w=="
|
"integrity": "sha512-ZigEmCWdNUU7IjZEuQ/iaimYdDHWHfTe3kg8ORfKjyGYd9RWumPoOJRQXB0bO+XLkNwzCthW3wUIQtANaEZ1ag=="
|
||||||
},
|
},
|
||||||
"@types/minimist": {
|
"@types/minimist": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
|
@ -13474,15 +13475,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"easymde": {
|
"easymde": {
|
||||||
"version": "2.15.0",
|
"version": "2.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/easymde/-/easymde-2.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/easymde/-/easymde-2.16.1.tgz",
|
||||||
"integrity": "sha512-9jMRIVvKt1d0UjRN45yotUYECAM4xvw0TTAQw8sYDONP++keWJVnd8Xrn+V+vQEN/v9/X0SWEoo1rFSgCooGpw==",
|
"integrity": "sha512-FihYgjRsKfhGNk89SHSqxKLC4aJ1kfybPWW6iAmtb5GnXu+tnFPSzSaGBmk1RRlCuhFSjhF0SnIMGVPjEzkr6g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/codemirror": "0.0.109",
|
"@types/codemirror": "^5.60.4",
|
||||||
"@types/marked": "^2.0.2",
|
"@types/marked": "^4.0.1",
|
||||||
"codemirror": "^5.61.0",
|
"codemirror": "^5.63.1",
|
||||||
"codemirror-spell-checker": "1.1.2",
|
"codemirror-spell-checker": "1.1.2",
|
||||||
"marked": "^2.0.3"
|
"marked": "^4.0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editorconfig-checker": {
|
"editorconfig-checker": {
|
||||||
|
@ -16117,9 +16118,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"marked": {
|
"marked": {
|
||||||
"version": "2.1.3",
|
"version": "4.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz",
|
||||||
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA=="
|
"integrity": "sha512-+QvuFj0nGgO970fySghXGmuw+Fd0gD2x3+MqCWLIPf5oxdv1Ka6b2q+z9RP01P/IaKPMEramy+7cNy/Lw8c3hw=="
|
||||||
},
|
},
|
||||||
"mathml-tag-names": {
|
"mathml-tag-names": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"name": "gitea",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base32"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func WebAuthnLoginAssertionPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success! Get the credential and update the sign count with the new value we received.
|
// Success! Get the credential and update the sign count with the new value we received.
|
||||||
dbCred, err := auth.GetWebAuthnCredentialByCredID(base64.RawStdEncoding.EncodeToString(cred.ID))
|
dbCred, err := auth.GetWebAuthnCredentialByCredID(user.ID, base32.HexEncoding.EncodeToString(cred.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetWebAuthnCredentialByCredID", err)
|
ctx.ServerError("GetWebAuthnCredentialByCredID", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -38,9 +38,9 @@ func WebAuthnRegister(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = ctx.Session.Delete("registration")
|
_ = ctx.Session.Delete("webauthnRegistration")
|
||||||
if err := ctx.Session.Set("WebauthnName", form.Name); err != nil {
|
if err := ctx.Session.Set("webauthnName", form.Name); err != nil {
|
||||||
ctx.ServerError("Unable to set session key for WebauthnName", err)
|
ctx.ServerError("Unable to set session key for webauthnName", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func WebAuthnRegister(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the session data as marshaled JSON
|
// Save the session data as marshaled JSON
|
||||||
if err = ctx.Session.Set("registration", sessionData); err != nil {
|
if err = ctx.Session.Set("webauthnRegistration", sessionData); err != nil {
|
||||||
ctx.ServerError("Unable to set session", err)
|
ctx.ServerError("Unable to set session", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -61,20 +61,20 @@ func WebAuthnRegister(ctx *context.Context) {
|
||||||
|
|
||||||
// WebauthnRegisterPost receives the response of the security key
|
// WebauthnRegisterPost receives the response of the security key
|
||||||
func WebauthnRegisterPost(ctx *context.Context) {
|
func WebauthnRegisterPost(ctx *context.Context) {
|
||||||
name, ok := ctx.Session.Get("WebauthnName").(string)
|
name, ok := ctx.Session.Get("webauthnName").(string)
|
||||||
if !ok || name == "" {
|
if !ok || name == "" {
|
||||||
ctx.ServerError("Get WebauthnName", errors.New("no WebauthnName"))
|
ctx.ServerError("Get webauthnName", errors.New("no webauthnName"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the session data
|
// Load the session data
|
||||||
sessionData, ok := ctx.Session.Get("registration").(*webauthn.SessionData)
|
sessionData, ok := ctx.Session.Get("webauthnRegistration").(*webauthn.SessionData)
|
||||||
if !ok || sessionData == nil {
|
if !ok || sessionData == nil {
|
||||||
ctx.ServerError("Get registration", errors.New("no registration"))
|
ctx.ServerError("Get registration", errors.New("no registration"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = ctx.Session.Delete("registration")
|
_ = ctx.Session.Delete("webauthnRegistration")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Verify that the challenge succeeded
|
// Verify that the challenge succeeded
|
||||||
|
@ -103,6 +103,8 @@ func WebauthnRegisterPost(ctx *context.Context) {
|
||||||
ctx.ServerError("CreateCredential", err)
|
ctx.ServerError("CreateCredential", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
_ = ctx.Session.Delete("webauthnName")
|
||||||
|
|
||||||
ctx.JSON(http.StatusCreated, cred)
|
ctx.JSON(http.StatusCreated, cred)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<div class="hide" data-webauthn-error-msg="duplicated"><p>{{.i18n.Tr "webauthn_error_duplicated"}}</div>
|
<div class="hide" data-webauthn-error-msg="duplicated"><p>{{.i18n.Tr "webauthn_error_duplicated"}}</div>
|
||||||
<div class="hide" data-webauthn-error-msg="empty"><p>{{.i18n.Tr "webauthn_error_empty"}}</div>
|
<div class="hide" data-webauthn-error-msg="empty"><p>{{.i18n.Tr "webauthn_error_empty"}}</div>
|
||||||
<div class="hide" data-webauthn-error-msg="timeout"><p>{{.i18n.Tr "webauthn_error_timeout"}}</div>
|
<div class="hide" data-webauthn-error-msg="timeout"><p>{{.i18n.Tr "webauthn_error_timeout"}}</div>
|
||||||
<div class="hide" data-webauthn-error-msg="0"></div>
|
<div class="hide" data-webauthn-error-msg="general"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
|
|
@ -28,16 +28,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui small modal" id="register-device">
|
|
||||||
<div class="header">{{.i18n.Tr "settings.webauthn_register_key"}}</div>
|
|
||||||
<div class="content">
|
|
||||||
<i class="notched spinner loading icon"></i> {{.i18n.Tr "settings.webauthn_press_button"}}
|
|
||||||
</div>
|
|
||||||
<div class="actions">
|
|
||||||
<div class="ui cancel button">{{.i18n.Tr "cancel"}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{template "user/auth/webauthn_error" .}}
|
{{template "user/auth/webauthn_error" .}}
|
||||||
|
|
||||||
<div class="ui small basic delete modal" id="delete-registration">
|
<div class="ui small basic delete modal" id="delete-registration">
|
||||||
|
|
|
@ -24,7 +24,7 @@ export function initUserAuthWebAuthn() {
|
||||||
.then((credential) => {
|
.then((credential) => {
|
||||||
verifyAssertion(credential);
|
verifyAssertion(credential);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
webAuthnError(0, err.message);
|
webAuthnError('general', err.message);
|
||||||
});
|
});
|
||||||
}).fail(() => {
|
}).fail(() => {
|
||||||
webAuthnError('unknown');
|
webAuthnError('unknown');
|
||||||
|
@ -113,11 +113,16 @@ function webauthnRegistered(newCredential) {
|
||||||
|
|
||||||
function webAuthnError(errorType, message) {
|
function webAuthnError(errorType, message) {
|
||||||
$('#webauthn-error [data-webauthn-error-msg]').hide();
|
$('#webauthn-error [data-webauthn-error-msg]').hide();
|
||||||
if (errorType === 0 && message && message.length > 1) {
|
const $errorGeneral = $(`#webauthn-error [data-webauthn-error-msg=general]`);
|
||||||
$(`#webauthn-error [data-webauthn-error-msg=0]`).text(message);
|
if (errorType === 'general') {
|
||||||
$(`#webauthn-error [data-webauthn-error-msg=0]`).show();
|
$errorGeneral.show().text(message || 'unknown error');
|
||||||
} else {
|
} else {
|
||||||
$(`#webauthn-error [data-webauthn-error-msg=${errorType}]`).show();
|
const $errorTyped = $(`#webauthn-error [data-webauthn-error-msg=${errorType}]`);
|
||||||
|
if ($errorTyped.length) {
|
||||||
|
$errorTyped.show();
|
||||||
|
} else {
|
||||||
|
$errorGeneral.show().text(`unknown error type: ${errorType}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$('#webauthn-error').modal('show');
|
$('#webauthn-error').modal('show');
|
||||||
}
|
}
|
||||||
|
@ -149,7 +154,6 @@ export function initUserAuthWebAuthnRegister() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#register-device').modal({allowMultiple: false});
|
|
||||||
$('#webauthn-error').modal({allowMultiple: false});
|
$('#webauthn-error').modal({allowMultiple: false});
|
||||||
$('#register-webauthn').on('click', (e) => {
|
$('#register-webauthn').on('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -167,7 +171,6 @@ function webAuthnRegisterRequest() {
|
||||||
name: $('#nickname').val(),
|
name: $('#nickname').val(),
|
||||||
}).done((makeCredentialOptions) => {
|
}).done((makeCredentialOptions) => {
|
||||||
$('#nickname').closest('div.field').removeClass('error');
|
$('#nickname').closest('div.field').removeClass('error');
|
||||||
$('#register-device').modal('show');
|
|
||||||
|
|
||||||
makeCredentialOptions.publicKey.challenge = decode(makeCredentialOptions.publicKey.challenge);
|
makeCredentialOptions.publicKey.challenge = decode(makeCredentialOptions.publicKey.challenge);
|
||||||
makeCredentialOptions.publicKey.user.id = decode(makeCredentialOptions.publicKey.user.id);
|
makeCredentialOptions.publicKey.user.id = decode(makeCredentialOptions.publicKey.user.id);
|
||||||
|
@ -185,7 +188,7 @@ function webAuthnRegisterRequest() {
|
||||||
webAuthnError('unknown');
|
webAuthnError('unknown');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
webAuthnError(0, err);
|
webAuthnError('general', err.message);
|
||||||
});
|
});
|
||||||
}).fail((xhr) => {
|
}).fail((xhr) => {
|
||||||
if (xhr.status === 409) {
|
if (xhr.status === 409) {
|
||||||
|
|
Loading…
Reference in a new issue