1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-26 18:21:01 +00:00

Add WebAuthn / Passkey integration

This is a rebase of #1618 in which @dave-atx added WebAuthn support.

Closes #1618
This commit is contained in:
Florian Rüchel 2023-11-06 04:27:35 +10:30 committed by GitHub
parent 62188b49f0
commit 62ef8ed57a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 1357 additions and 33 deletions

View file

@ -44,12 +44,22 @@
<script src="{{ route "javascript" "name" "app" "checksum" .app_js_checksum }}" defer></script>
<script src="{{ route "javascript" "name" "service-worker" "checksum" .sw_js_checksum }}" defer id="service-worker-script"></script>
{{ if .webAuthnEnabled }}
<script src="{{ route "javascript" "name" "webauthn" "checksum" .webauthn_js_checksum }}" defer></script>
{{ end }}
</head>
<body
{{ if .csrf }}data-csrf-token="{{ .csrf }}"{{ end }}
data-add-subscription-url="{{ route "addSubscription" }}"
data-entries-status-url="{{ route "updateEntriesStatus" }}"
data-refresh-all-feeds-url="{{ route "refreshAllFeeds" }}"
{{ if .webAuthnEnabled }}
data-webauthn-register-begin-url="{{ route "webauthnRegisterBegin" }}"
data-webauthn-register-finish-url="{{ route "webauthnRegisterFinish" }}"
data-webauthn-login-begin-url="{{ route "webauthnLoginBegin" }}"
data-webauthn-login-finish-url="{{ route "webauthnLoginFinish" }}"
data-webauthn-delete-all-url="{{ route "webauthnDeleteAll" }}"
{{ end }}
{{ if .user }}{{ if not .user.KeyboardShortcuts }}data-disable-keyboard-shortcuts="true"{{ end }}{{ end }}>
{{ if .user }}

View file

@ -19,6 +19,14 @@
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.loading" }}">{{ t "action.login" }}</button>
</div>
</form>
{{ if .webAuthnEnabled }}
<div class="alert alert-error hidden" id="webauthn-error">
{{ t "page.login.webauthn_login.error" }}
</div>
<div class="buttons">
<button class="button" id="webauthn-login" disabled>{{ t "page.login.webauthn_login" }}</button>
</div>
{{ end }}
{{ if hasOAuth2Provider "google" }}
<div class="oauth2">
<a href="{{ route "oauth2Redirect" "provider" "google" }}">{{ t "page.login.google_signin" }}</a>

View file

@ -46,7 +46,56 @@
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>
</fieldset>
{{ if .webAuthnEnabled }}
<fieldset>
<legend>{{ t "page.settings.webauthn.passkeys" }}</legend>
<div class="alert alert-error hidden" id="webauthn-error">
{{ t "page.settings.webauthn.register.error" }}
</div>
<div class="buttons">
<button class="button" id="webauthn-register" disabled>
{{ t "page.settings.webauthn.register" }}
</button>
{{ if gt .countWebAuthnCerts 0}}
<button class="button" id="webauthn-delete">
{{ plural "page.settings.webauthn.delete" .countWebAuthnCerts .countWebAuthnCerts }}
</button>
{{ end }}
</div>
{{ if .webAuthnCerts}}
<div class="details-content">
<table>
<tr>
<th>{{ t "page.settings.webauthn.passkey_name" }}</th>
<th>{{ t "page.settings.webauthn.added_on" }}</th>
<th>{{ t "page.settings.webauthn.last_seen_on" }}</th>
<th>{{ t "page.settings.webauthn.actions" }}</th>
</tr>
{{ range .webAuthnCerts }}
<tr>
<td>{{ .Name }}</td>
<td>{{ elapsed $.user.Timezone .AddedOn }}</td>
<td>{{ elapsed $.user.Timezone .LastSeenOn }}</td>
<td>
<a href="#"
data-confirm="true"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-url="{{ route "webauthnDelete" "credentialHandle" .HandleEncoded }}">{{ icon "delete" }}{{ t "action.remove" }}</a>
<a href="{{ route "webauthnRename" "credentialHandle" .HandleEncoded }}">{{ icon "edit" }} {{ t "action.edit" }}</a>
</td>
</tr>
{{ end }}
</table>
</div>
{{ end }}
</fieldset>
{{ end }}
<fieldset>
<legend>{{ t "form.prefs.fieldset.reader_settings" }}</legend>

View file

@ -0,0 +1,22 @@
{{ define "title"}}{{ t "page.webauthn_rename.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.webauthn_rename.title" }}</h1>
</section>
<form action="{{ route "webauthnSave" "credentialHandle" .cred.HandleEncoded }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ .errorMessage }}</div>
{{ end }}
<label for="form-title">{{ t "page.settings.webauthn.passkey_name" }}</label>
<input type="text" name="name" id="form-title" value="{{ .form.Name }}" autofocus>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>
</form>
{{ end }}