Clean up WebAuthn javascript code and remove JQuery code (#22697)
There were several issues with the WebAuthn registration and testing code and the style was very old javascript with jquery callbacks. This PR uses async and fetch to replace the JQuery code. Ref #22651 Signed-off-by: Andrew Thornton <art27@cantab.net> --------- Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: delvh <dev.lh@web.de> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@ -6,6 +6,8 @@ package security
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
wa "code.gitea.io/gitea/modules/auth/webauthn"
|
||||
@ -23,8 +25,8 @@ import (
|
||||
func WebAuthnRegister(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.WebauthnRegistrationForm)
|
||||
if form.Name == "" {
|
||||
ctx.Error(http.StatusConflict)
|
||||
return
|
||||
// Set name to the hexadecimal of the current time
|
||||
form.Name = strconv.FormatInt(time.Now().UnixNano(), 16)
|
||||
}
|
||||
|
||||
cred, err := auth.GetWebAuthnCredentialByName(ctx.Doer.ID, form.Name)
|
||||
|
@ -5,6 +5,7 @@
|
||||
<h3 class="ui top attached header">
|
||||
{{.locale.Tr "twofa"}}
|
||||
</h3>
|
||||
{{template "user/auth/webauthn_error" .}}
|
||||
<div class="ui attached segment">
|
||||
{{svg "octicon-key" 56}}
|
||||
<h3>{{.locale.Tr "webauthn_insert_key"}}</h3>
|
||||
@ -18,5 +19,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "user/auth/webauthn_error" .}}
|
||||
{{template "base/footer" .}}
|
||||
|
@ -1,22 +1,13 @@
|
||||
<div class="ui small modal" id="webauthn-error">
|
||||
<div class="header">{{.locale.Tr "webauthn_error"}}</div>
|
||||
<div class="content">
|
||||
<div class="ui negative message">
|
||||
<div class="header">
|
||||
{{.locale.Tr "webauthn_error"}}
|
||||
</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="browser"><p>{{.locale.Tr "webauthn_unsupported_browser"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="unknown"><p>{{.locale.Tr "webauthn_error_unknown"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="insecure"><p>{{.locale.Tr "webauthn_error_insecure"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="unable-to-process"><p>{{.locale.Tr "webauthn_error_unable_to_process"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="duplicated"><p>{{.locale.Tr "webauthn_error_duplicated"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="empty"><p>{{.locale.Tr "webauthn_error_empty"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="timeout"><p>{{.locale.Tr "webauthn_error_timeout"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="general"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button onclick="window.location.reload()" class="success ui button gt-hidden webauthn_error_timeout">{{.locale.Tr "webauthn_reload"}}</button>
|
||||
<button class="ui cancel button">{{.locale.Tr "cancel"}}</button>
|
||||
<div id="webauthn-error" class="ui small gt-hidden">
|
||||
<div class="content ui negative message gt-df gt-fc gt-gap-3">
|
||||
<div class="header">{{.locale.Tr "webauthn_error"}}</div>
|
||||
<div id="webauthn-error-msg"></div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="browser">{{.locale.Tr "webauthn_unsupported_browser"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="unknown">{{.locale.Tr "webauthn_error_unknown"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="insecure">{{.locale.Tr "webauthn_error_insecure"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="unable-to-process">{{.locale.Tr "webauthn_error_unable_to_process"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="duplicated">{{.locale.Tr "webauthn_error_duplicated"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="empty">{{.locale.Tr "webauthn_error_empty"}}</div>
|
||||
<div class="gt-hidden" data-webauthn-error-msg="timeout">{{.locale.Tr "webauthn_error_timeout"}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<p>{{.locale.Tr "settings.webauthn_desc" | Str2html}}</p>
|
||||
{{template "user/auth/webauthn_error" .}}
|
||||
<div class="ui key list">
|
||||
{{range .WebAuthnCredentials}}
|
||||
<div class="item">
|
||||
@ -28,7 +29,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "user/auth/webauthn_error" .}}
|
||||
|
||||
<div class="ui g-modal-confirm delete modal" id="delete-registration">
|
||||
<div class="header">
|
||||
|
@ -699,6 +699,11 @@ a.label,
|
||||
border: 1px solid var(--color-secondary);
|
||||
}
|
||||
|
||||
.ui.info.message .header,
|
||||
.ui.blue.message .header {
|
||||
color: var(--color-blue);
|
||||
}
|
||||
|
||||
.ui.info.message,
|
||||
.ui.attached.info.message,
|
||||
.ui.blue.message,
|
||||
@ -708,6 +713,12 @@ a.label,
|
||||
border-color: var(--color-info-border);
|
||||
}
|
||||
|
||||
.ui.success.message .header,
|
||||
.ui.positive.message .header,
|
||||
.ui.green.message .header {
|
||||
color: var(--color-green);
|
||||
}
|
||||
|
||||
.ui.success.message,
|
||||
.ui.attached.success.message,
|
||||
.ui.positive.message,
|
||||
@ -717,6 +728,12 @@ a.label,
|
||||
border-color: var(--color-success-border);
|
||||
}
|
||||
|
||||
.ui.error.message .header,
|
||||
.ui.negative.message .header,
|
||||
.ui.red.message .header {
|
||||
color: var(--color-red);
|
||||
}
|
||||
|
||||
.ui.error.message,
|
||||
.ui.attached.error.message,
|
||||
.ui.red.message,
|
||||
@ -728,6 +745,11 @@ a.label,
|
||||
border-color: var(--color-error-border);
|
||||
}
|
||||
|
||||
.ui.warning.message .header,
|
||||
.ui.yellow.message .header {
|
||||
color: var(--color-yellow);
|
||||
}
|
||||
|
||||
.ui.warning.message,
|
||||
.ui.attached.warning.message,
|
||||
.ui.yellow.message,
|
||||
|
@ -2405,11 +2405,6 @@
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.settings .content > .header,
|
||||
.settings .content .segment {
|
||||
box-shadow: 0 1px 2px 0 var(--color-box-header);
|
||||
}
|
||||
|
||||
.settings.webhooks .list > .item:not(:first-child),
|
||||
.settings.githooks .list > .item:not(:first-child),
|
||||
.settings.actions .list > .item:not(:first-child) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,5 @@
|
||||
import {encode, decode} from 'uint8-to-base64';
|
||||
|
||||
// transform /path/to/file.ext to file.ext
|
||||
export function basename(path = '') {
|
||||
return path ? path.replace(/^.*\//, '') : '';
|
||||
@ -135,3 +137,17 @@ export function toAbsoluteUrl(url) {
|
||||
return `${window.location.origin}${url}`;
|
||||
}
|
||||
|
||||
// Encode an ArrayBuffer into a URLEncoded base64 string.
|
||||
export function encodeURLEncodedBase64(arrayBuffer) {
|
||||
return encode(arrayBuffer)
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=/g, '');
|
||||
}
|
||||
|
||||
// Decode a URLEncoded base64 to an ArrayBuffer string.
|
||||
export function decodeURLEncodedBase64(base64url) {
|
||||
return decode(base64url
|
||||
.replace(/_/g, '/')
|
||||
.replace(/-/g, '+'));
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import {expect, test} from 'vitest';
|
||||
import {
|
||||
basename, extname, isObject, stripTags, joinPaths, parseIssueHref,
|
||||
parseUrl, translateMonth, translateDay, blobToDataURI,
|
||||
toAbsoluteUrl,
|
||||
toAbsoluteUrl, encodeURLEncodedBase64, decodeURLEncodedBase64,
|
||||
} from './utils.js';
|
||||
|
||||
test('basename', () => {
|
||||
@ -132,3 +132,9 @@ test('toAbsoluteUrl', () => {
|
||||
|
||||
expect(() => toAbsoluteUrl('path')).toThrowError('unsupported');
|
||||
});
|
||||
|
||||
test('encodeURLEncodedBase64, decodeURLEncodedBase64', () => {
|
||||
expect(encodeURLEncodedBase64(decodeURLEncodedBase64('foo'))).toEqual('foo'); // No = padding
|
||||
expect(encodeURLEncodedBase64(decodeURLEncodedBase64('a-minus'))).toEqual('a-minus');
|
||||
expect(encodeURLEncodedBase64(decodeURLEncodedBase64('_underscorc'))).toEqual('_underscorc');
|
||||
});
|
||||
|
Reference in New Issue
Block a user