Fixing functionality

This commit is contained in:
= 2019-09-02 09:42:24 -05:00
parent edb16382f3
commit 25ef7b5675
Signed by: kiichan
GPG Key ID: 619DFD67F0976616
14 changed files with 76 additions and 27 deletions

View File

@ -1,3 +1,19 @@
Mon, 02 Sep 2019 09:42:24 -0500
Keaton <kii-chan@tutanota.com>
Fixing functionality
A bare-bones test server was set up and account creation and authentication was
achieved through SQRL. Old documentation needs to be updated, and new
documentation needs to be written (mostly for using the drop-in login).
At this point, the SQRL authentication protocol for Django is functional!
Further work needs to be done to test drop-in support for already-running sites.
If possible, that would be the ideal end goal; making it as easy as possible to
propagate SQRL through the internet.
--------------------
Mon, 02 Sep 2019 04:56:45 -0500
Keaton <kii-chan@tutanota.com>
Completing functional conversions

View File

@ -1 +1,3 @@
Django
django-braces
ed25519

View File

@ -1,3 +1,30 @@
# -*- coding: utf-8 -*-
from django.contrib import admin
# Register your models here.
from .models import SQRLIdentity, SQRLNut
class SQRLIdentityAdmin(admin.ModelAdmin):
model = SQRLIdentity
list_display = (
'user',
'is_enabled',
'is_only_sqrl',
)
raw_id_fields = (
'user',
)
class SQRLNutAdmin(admin.ModelAdmin):
model = SQRLNut
list_display = (
'nonce',
'is_transaction_complete',
'ip_address',
)
admin.site.register(SQRLNut, SQRLNutAdmin)
admin.site.register(SQRLIdentity, SQRLIdentityAdmin)

View File

@ -190,6 +190,10 @@ class RequestForm(forms.Form):
pidk = self.cleaned_data['client'].get('pidk')
pids = self.cleaned_data.get('pids')
if not any((pids, pidk)):
# There are no previous ID key/secrets, which shouldn't break the validation.
return pids
if not all((pids, pidk)):
raise forms.ValidationError(
'Cannot validate previous ID signature without server knowing pid public and secret keys.'

View File

@ -45,11 +45,11 @@ class SQRLHttpResponse(HttpResponse):
for k, v in normalized_data.items():
self['X-SQRL-{}'.format(k)] = v
log.debug('Response encoded data:\n{}'
log.error('Response encoded data:\n{}'
''.format(content))
log.debug('Response data:\n{}'
log.error('Response data:\n{}'
''.format(pformat(normalized_data)))
log.debug('Response TIF breakdown:\n{}'
log.error('Response TIF breakdown:\n{}'
''.format(pformat(TIF(int(data['tif'], 16)).breakdown())))
def sign_response(self, nut, data):

View File

@ -139,7 +139,7 @@ class SQRLInitialization(object):
"""
return (
'{scheme}://{host}{url}'
''.format(scheme='sqrl', if self.request.is_secure() else 'qrl',
''.format(scheme='sqrl' if self.request.is_secure() else 'qrl',
host=self.request.get_host(),
url=self.url)
)

View File

@ -4,7 +4,7 @@
return input.length > 0 ? input[0].value : null;
},
current_url = window.location.href,
sqrl_frequency = 1500,
sqrl_frequency = 2500,
sqrl_call = function() {
setTimeout(sqrl_handler, sqrl_frequency);
},
@ -29,6 +29,7 @@
var data = JSON.parse(this.responseText);
if (data.transaction_complete === true) {
if (data.redirect_to !== undefined) {
console.log(data.redirect_to);
window.location.href = data.redirect_to;
} else {
console.error('Server indicated that SQRL transaction is complete ' +
@ -44,6 +45,7 @@
try {
request.send(null);
} catch (exception) {
console.log("stopping requests due to error??");
// do not send anymore requests if error occurred
}
};

View File

@ -14,6 +14,6 @@
{% if user.has_usable_password %}
<a href="{% url 'admin:password_change' %}">{% trans 'Change password' %}</a> /
{% endif %}
<a href="{% url 'admin-sqrl_manage' %}">{% trans 'Manage SQRL' %}</a> /
<a href="{% url 'sqrl:admin-sqrl_manage' %}">{% trans 'Manage SQRL' %}</a> /
<a href="{% url 'admin:logout' %}">{% trans 'Log out' %}</a>
{% endblock %}

View File

@ -12,7 +12,7 @@
</p>
{% sqrl as session_sqrl %}
{% sqrl_login_dropin session_sqrl %}
{% sqrl_login_dropin session_sqrl login %}
{% endblock %}
{% comment %}

View File

@ -7,11 +7,12 @@
<p>
Already have account?
Login <a href="{% url 'login' %}">here</a> to associate
SQRL identity with existing account.
Login <a href="{% url 'sqrl:login' %}">here</a> to associate
SQRL identity with an existing account.
</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>

View File

@ -28,13 +28,8 @@
</div>
<input type="hidden" name="nut" value="{{ session_sqrl.nut.nonce }}">
{% if session_sqrl.method == "manage" %}
{# redirect to manage page after successful SQRL transaction #}
<input type="hidden" name="next" value="{% url 'sqrl:manage' %}">
<input type="submit" value="Manage SQRL">
{% else %}
<input type="submit" value="Log in using SQRL">
{% endif %}
<input type="hidden" name="next" value="{{ redir }}">
<input type="submit" value="Authenticate using SQRL">
</form>
</div>
<script>SQRL_CHECK_URL="{% sqrl_status_url_script_tag session_sqrl %}"</script>

View File

@ -7,7 +7,6 @@ from ..sqrl import SQRLInitialization
register = template.Library()
print(register)
@register.simple_tag(takes_context=True)
@ -16,7 +15,7 @@ def sqrl(context):
@register.inclusion_tag('sqrl/sqrl-dropin.html')
def sqrl_login_dropin(session_sqrl, method="login"):
def sqrl_login_dropin(session_sqrl, redir):
"""
Creates a drop-in SQRL element in your template pages.
Add it to your login template to make it SQRL-aware.
@ -24,19 +23,17 @@ def sqrl_login_dropin(session_sqrl, method="login"):
Usage:
{% load sqrl %}
{% sqrl as session_sqrl %}
{% sqrl_login_dropin session_sqrl [method=METHOD] %}
{% sqrl_login_dropin session_sqrl REDIR %}
METHOD is an optional argument that changes the way the form
behaves. Possible arguments are:
- login: The default method. No special redirections occur
- manage: Will redirect the user to sqrl/manage
REDIR is the registered name of the page to move to once the login
is completed.
Notes:
The drop-in is defaulted to a max-width of 300px. Set the width
property of the parent if you want or need it smaller. You will
likely want to change the font-size as well in this case.
"""
return {'session_sqrl':session_sqrl, 'method': method}
return {'session_sqrl':session_sqrl, 'redir': reverse(redir)}
@register.simple_tag

View File

@ -7,6 +7,7 @@ from .views import (
SQRLIdentityManagementView,
SQRLLoginView,
SQRLStatusView,
AdminSiteSQRLIdentityManagementView
)
app_name = "sqrl"
@ -17,4 +18,5 @@ urlpatterns = [
path("manage/", SQRLIdentityManagementView.as_view(), name='manage'),
path("register/",SQRLCompleteRegistrationView.as_view(), name='complete-registration'),
re_path(r"^status/(?P<transaction>[A-Za-z0-9_-]{43})/$", SQRLStatusView.as_view(), name='status'),
path('admin/sqrl_manage/', AdminSiteSQRLIdentityManagementView.as_view(), name='admin-sqrl_manage'),
]

View File

@ -17,6 +17,8 @@ from django.urls import reverse
from django.http import Http404, HttpResponse, JsonResponse, QueryDict
from django.shortcuts import get_object_or_404, redirect
from django.views.generic import FormView, TemplateView, View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from .backends import SQRL_MODEL_BACKEND
from .exceptions import TIF, TIFException
@ -51,7 +53,7 @@ class SQRLLoginView(TemplateView):
"""
template_name = 'sqrl/login.html'
@method_decorator(csrf_exempt,"dispatch")
class SQRLStatusView(View):
"""
Ajax view which returns the status of the SQRL transaction back to the user.
@ -96,7 +98,7 @@ class SQRLStatusView(View):
else:
url = self.success_url
if all([not self.request.user.is_authenticated(),
if all([not self.request.user.is_authenticated,
SQRL_IDENTITY_SESSION_KEY in self.request.session]):
return reverse('sqrl:complete-registration') + '?next={}'.format(url)
else:
@ -140,6 +142,7 @@ class SQRLStatusView(View):
return JsonResponse(data)
@method_decorator(csrf_exempt,"dispatch")
class SQRLAuthView(View):
"""
This is the main view responsible for all interactions with SQRL client.