mirror of https://gitlab.com/tildes/tildes.git
Browse Source
Merge branch 'webauthn' into 'master'
Merge branch 'webauthn' into 'master'
Draft: #646 Implement Webauthn support See merge request tildes/tildes!140merge-requests/140/merge
10 changed files with 235 additions and 5 deletions
-
2tildes/requirements-dev.txt
-
1tildes/requirements.txt
-
28tildes/tildes/models/user/user.py
-
26tildes/tildes/templates/intercooler/login_webauthn.jinja2
-
5tildes/tildes/templates/intercooler/webauthn_disabled.jinja2
-
4tildes/tildes/templates/intercooler/webauthn_enabled.jinja2
-
59tildes/tildes/templates/settings_webauthn.jinja2
-
45tildes/tildes/views/api/web/user.py
-
47tildes/tildes/views/login.py
-
23tildes/tildes/views/settings.py
@ -0,0 +1,26 @@ |
|||||
|
{# Copyright (c) 2018 Tildes contributors <code@tildes.net> #} |
||||
|
{# SPDX-License-Identifier: AGPL-3.0-or-later #} |
||||
|
|
||||
|
<p>WebAuthn authentication is enabled on this account. Please use your authenticator when prompted. If you do not have access to your authenticator device, enter a backup code.</p> |
||||
|
|
||||
|
<form id="webauthn-login-form" class="form-narrow" method="post" autocomplete="off" action="/login_webauthn" data-ic-post-to="/login_webauthn" onload="assertCredentials()"> |
||||
|
<input type="hidden" name="csrf_token" value="{{ get_csrf_token() }}" /> |
||||
|
<input type="hidden" name="from_url" value="{{ from_url }}" /> |
||||
|
{% if keep %} |
||||
|
<input type="hidden" name="keep" value="on" /> |
||||
|
{% endif %} |
||||
|
<input class="form-input" id="assertion" name="assertion" type="hidden" /> |
||||
|
<script> |
||||
|
const auth_options = JSON.parse(atob('{{ auth_options }}')); |
||||
|
function assertCredentials() { |
||||
|
navigator.credentials.get(auth_options).then((credential) => { |
||||
|
document.getElementById("#webauthn-login-form").submit() |
||||
|
document.getElementById("#assertion").text(btoa(credential.response)); |
||||
|
}); |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<div class="form-buttons"> |
||||
|
<button class="btn btn-primary" type="submit">Continue</button> |
||||
|
</div> |
||||
|
</form> |
@ -0,0 +1,5 @@ |
|||||
|
{# Copyright (c) 2018 Tildes contributors <code@tildes.net> #} |
||||
|
{# SPDX-License-Identifier: AGPL-3.0-or-later #} |
||||
|
|
||||
|
<p>Webauthn authentication has been disabled. You will no longer need a code when logging in.</p> |
||||
|
|
@ -0,0 +1,4 @@ |
|||||
|
{# Copyright (c) 2018 Tildes contributors <code@tildes.net> #} |
||||
|
{# SPDX-License-Identifier: AGPL-3.0-or-later #} |
||||
|
|
||||
|
<p>Congratulations! Webauthn authentication has been enabled.</p> |
@ -0,0 +1,59 @@ |
|||||
|
{# Copyright (c) 2018 Tildes contributors <code@tildes.net> #} |
||||
|
{# SPDX-License-Identifier: AGPL-3.0-or-later #} |
||||
|
|
||||
|
{% extends 'base_settings.jinja2' %} |
||||
|
|
||||
|
{% block title %}Set up webauthn authentication{% endblock %} |
||||
|
|
||||
|
{% block main_heading %}Set up webauthn authentication{% endblock %} |
||||
|
|
||||
|
{% block settings %} |
||||
|
{% if request.user.webauthn_enabled %} |
||||
|
|
||||
|
<div class="divider"></div> |
||||
|
|
||||
|
<p>To disable webauthn authentication, click the button below</p> |
||||
|
|
||||
|
<form |
||||
|
name="disable-webauthn" |
||||
|
autocomplete="off" |
||||
|
data-ic-post-to="{{ request.route_url('ic_user', username=request.user.username) }}" |
||||
|
data-ic-target="closest main" |
||||
|
> |
||||
|
|
||||
|
<div class="form-buttons"> |
||||
|
<button class="btn btn-error" type="submit">Disable webauthn authentication</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
{% else %} |
||||
|
<p>To get started, you'll need an authenticator such as a Yubikey, or you can use your specific computer as an authenticator</p> |
||||
|
|
||||
|
<p>Next, click below to enroll your authenticator</p> |
||||
|
<script> |
||||
|
// It would probably be a lot better to load this on demand when trying to enroll an authenticator |
||||
|
const credential_options = JSON.parse(atob('{{ webauthn_challenge }}')) |
||||
|
|
||||
|
function enrollAuthenticator() { |
||||
|
navigator.credentials.create(credential_options).then((credentials) => { |
||||
|
document.getElementById("#webauthn-assertion").text(btoa(JSON.stringify(credentials.response))); |
||||
|
return true; |
||||
|
}); |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<div class="divider"></div> |
||||
|
|
||||
|
<form |
||||
|
name="enable-webauthn" |
||||
|
autocomplete="off" |
||||
|
data-ic-post-to="{{ request.route_url('ic_user', username=request.user.username) }}" |
||||
|
data-ic-target="closest main" |
||||
|
> |
||||
|
<input class="form-input" id="webauthn-assertion" name="webauthn-assertion" type="hidden" /> |
||||
|
|
||||
|
<div class="form-buttons"> |
||||
|
<button class="btn btn-primary" type="submit" onclick="enrollAuthenticator()">Enable Webauthn</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
{% endif %} |
||||
|
{% endblock %} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue