-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathtest_fido.py
142 lines (120 loc) · 6.01 KB
/
test_fido.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import json
from base64 import urlsafe_b64encode
from importlib import import_module
from django.http import HttpRequest
from django.test import RequestFactory,TransactionTestCase, Client
from django.urls import reverse
from django.conf import settings
from test_app.soft_webauthn import SoftWebauthnDevice
from passkeys.models import UserPasskey
def get_server_id(request):
return request.META["SERVER_NAME"] + "1"
def get_server_name(request):
return "MySite"
class test_fido(TransactionTestCase):
def setUp(self) -> None:
from django.contrib.auth import get_user_model
self.user_model = get_user_model()
if self.user_model.objects.filter(username="test").count()==0:
self.user = self.user_model.objects.create_user(username="test",password="test")
else:
self.user = self.user_model.objects.get(username="test")
self.client = Client()
settings.SESSION_ENGINE = 'django.contrib.sessions.backends.file'
engine = import_module(settings.SESSION_ENGINE)
#settings.SESSION_FILE_PATH = "/"
store = engine.SessionStore()
store.save(must_create=True)
self.session = store
self.client.cookies["sessionid"] = store.session_key
self.client.post("/auth/login", {"username": "test", "password": "test", 'passkeys': ''})
self.factory = RequestFactory()
def test_key_reg(self):
self.client.post('auth/login',{"usernaame":"test","password":"test","passkeys":""})
r = self.client.get(reverse('passkeys:reg_begin'))
self.assertEqual(r.status_code, 200)
j = json.loads(r.content)
j['publicKey']['challenge'] = j['publicKey']['challenge'].encode("ascii")
s = SoftWebauthnDevice()
res = s.create(j, "https://" + j["publicKey"]["rp"]["id"])
res["key_name"]="testKey"
u = reverse('passkeys:reg_complete')
r = self.client.post(u, data=json.dumps(res),headers={"USER_AGENT":""}, HTTP_USER_AGENT="", content_type="application/json")
try:
j = json.loads(r.content)
except Exception:
raise AssertionError("Failed to get the required JSON after reg_completed")
self.assertTrue("status" in j)
self.assertEqual(j["status"], "OK")
self.assertEqual(UserPasskey.objects.latest('id').name, "testKey")
return s
def test_auto_key_name(self):
r = self.client.get(reverse('passkeys:reg_begin'))
self.assertEqual(r.status_code, 200)
j = json.loads(r.content)
j['publicKey']['challenge'] = j['publicKey']['challenge'].encode("ascii")
s = SoftWebauthnDevice()
res = s.create(j, "https://" + j["publicKey"]["rp"]["id"])
u = reverse('passkeys:reg_complete')
r = self.client.post(u, data=json.dumps(res), HTTP_USER_AGENT="Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15", content_type="application/json")
try:
j = json.loads(r.content)
except Exception:
raise AssertionError("Failed to get the required JSON after reg_completed")
self.assertTrue("status" in j)
self.assertEqual(j["status"], "OK")
self.assertEqual(UserPasskey.objects.latest('id').name,"Apple")
return s
def test_error_when_no_session(self):
res = {}
res["key_name"] = "testKey"
u = reverse('passkeys:reg_complete')
r = self.client.post(u, data=json.dumps(res), headers={"USER_AGENT": ""}, HTTP_USER_AGENT="",
content_type="application/json")
try:
j = json.loads(r.content)
except Exception:
raise AssertionError("Failed to get the required JSON after reg_completed")
self.assertTrue("status" in j)
self.assertEqual(j["status"], "ERR")
self.assertEqual(j["message"], "FIDO Status can't be found, please try again")
def test_passkey_login(self):
authenticator = self.test_key_reg()
self.client.get('/auth/logout')
r = self.client.get(reverse('passkeys:auth_begin'))
self.assertEqual(r.status_code, 200)
j = json.loads(r.content)
j['publicKey']['challenge'] = j['publicKey']['challenge'].encode("ascii")
res = authenticator.get(j, "https://" + j["publicKey"]["rpId"])
u = reverse('login')
self.client.post(u, {'passkeys': json.dumps(res), "username": "", "password": ""},headers={"USER_AGENT":""}, HTTP_USER_AGENT="")
self.assertTrue(self.client.session.get('_auth_user_id',False))
self.assertTrue(self.client.session.get("passkey",{}).get("passkey",False))
self.assertEqual(self.client.session.get("passkey",{}).get("name"),"testKey")
def test_base_username(self):
authenticator = self.test_key_reg()
self.client.get('/auth/logout')
session = self.session
session["base_username"]= "test"
session.save(must_create=True)
self.client.cookies["sessionid"] = session.session_key
r = self.client.get(reverse('passkeys:auth_begin'))
self.assertEqual(r.status_code, 200)
j = json.loads(r.content)
self.assertEqual(j['publicKey']['allowCredentials'][0]['id'],urlsafe_b64encode(authenticator.credential_id).decode("utf8").strip('='))
def test_passkey_login_no_session(self):
pass
def test_server_id_callable(self):
from test_app.tests.test_fido import get_server_id
settings.FIDO_SERVER_ID = get_server_id
r = self.client.get(reverse('passkeys:auth_begin'))
self.assertEqual(r.status_code, 200)
j = json.loads(r.content)
self.assertEqual(j['publicKey']['rpId'],'testserver1')
def test_server_name_callable(self):
from test_app.tests.test_fido import get_server_name
settings.FIDO_SERVER_NAME = get_server_name
r = self.client.get(reverse('passkeys:reg_begin'))
self.assertEqual(r.status_code, 200)
j = json.loads(r.content)
self.assertEqual(j['publicKey']['rp']["name"],'MySite')