mirror of
https://github.com/morgan9e/virtual-webauthn
synced 2026-04-14 16:24:21 +09:00
Added Multiple choice when allowCredentials is empty
This commit is contained in:
25
fido.py
25
fido.py
@@ -313,6 +313,7 @@ class VirtualFidoDevice:
|
|||||||
|
|
||||||
allowed_credential = data.get("allowCredentials")
|
allowed_credential = data.get("allowCredentials")
|
||||||
cred = None
|
cred = None
|
||||||
|
|
||||||
if allowed_credential:
|
if allowed_credential:
|
||||||
for credential in allowed_credential:
|
for credential in allowed_credential:
|
||||||
credential_id_b64 = credential["id"]
|
credential_id_b64 = credential["id"]
|
||||||
@@ -320,10 +321,22 @@ class VirtualFidoDevice:
|
|||||||
cred = self.credentials[credential_id_b64]
|
cred = self.credentials[credential_id_b64]
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
for credential_id_b64, my_credential in self.credentials.items():
|
match_creds = []
|
||||||
if my_credential["rp_id"] == rp_id.decode():
|
for cid, cr in self.credentials.items():
|
||||||
cred = my_credential
|
if cr["rp_id"] == rp_id.decode():
|
||||||
break
|
match_creds.append(cid)
|
||||||
|
|
||||||
|
if len(match_creds) == 1:
|
||||||
|
cred = self.credentials[cid]
|
||||||
|
|
||||||
|
else:
|
||||||
|
results = []
|
||||||
|
for cr in match_creds:
|
||||||
|
current = data.copy()
|
||||||
|
current["allowCredentials"] = [{"id": cr}]
|
||||||
|
results.append(self.get(current, origin))
|
||||||
|
return results
|
||||||
|
|
||||||
if not cred:
|
if not cred:
|
||||||
raise self.CredNotFoundError()
|
raise self.CredNotFoundError()
|
||||||
|
|
||||||
@@ -360,7 +373,9 @@ class VirtualFidoDevice:
|
|||||||
"signature": self._b64url(signature),
|
"signature": self._b64url(signature),
|
||||||
"userHandle": cred["user_id"]
|
"userHandle": cred["user_id"]
|
||||||
},
|
},
|
||||||
"type": "public-key"
|
"type": "public-key",
|
||||||
|
"username": cred["user_name"],
|
||||||
|
"created": cred["created"]
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,43 @@ function myFetch(url, options = {}) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showCredentialSelectionPopup(credentials) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const popup = document.createElement("div");
|
||||||
|
popup.style.position = "fixed";
|
||||||
|
popup.style.top = "20px";
|
||||||
|
popup.style.right = "20px";
|
||||||
|
popup.style.backgroundColor = "#fff";
|
||||||
|
popup.style.color = "#000";
|
||||||
|
popup.style.border = "1px solid #bbb";
|
||||||
|
popup.style.borderRadius = "5px";
|
||||||
|
popup.style.padding = "15px";
|
||||||
|
popup.style.zIndex = "9999";
|
||||||
|
popup.style.maxWidth = "300px";
|
||||||
|
|
||||||
|
const title = document.createElement("h3");
|
||||||
|
title.textContent = "Select credential";
|
||||||
|
title.style.margin = "0 0 10px 0";
|
||||||
|
popup.appendChild(title);
|
||||||
|
|
||||||
|
credentials.forEach((cred, index) => {
|
||||||
|
const option = document.createElement("div");
|
||||||
|
option.style.padding = "8px 10px";
|
||||||
|
option.style.cursor = "pointer";
|
||||||
|
const createdDate = new Date(cred.created * 1000).toLocaleString();
|
||||||
|
option.innerHTML = `
|
||||||
|
<strong>${cred.username || 'Unknown user'}</strong>
|
||||||
|
<div style="font-size: 0.8em; color: #666;">Created: ${createdDate}</div>
|
||||||
|
`;
|
||||||
|
option.addEventListener("mouseover", () => { option.style.backgroundColor = "#f0f0f0"; });
|
||||||
|
option.addEventListener("mouseout", () => { option.style.backgroundColor = "transparent"; });
|
||||||
|
option.addEventListener("click", () => { document.body.removeChild(popup); resolve(cred); });
|
||||||
|
popup.appendChild(option);
|
||||||
|
});
|
||||||
|
document.body.appendChild(popup);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const origGet = navigator.credentials.get;
|
const origGet = navigator.credentials.get;
|
||||||
const origCreate = navigator.credentials.create;
|
const origCreate = navigator.credentials.create;
|
||||||
|
|
||||||
@@ -79,19 +116,23 @@ navigator.credentials.get = async function(options) {
|
|||||||
if (!response.ok) throw new Error(`server error: ${response.status}`)
|
if (!response.ok) throw new Error(`server error: ${response.status}`)
|
||||||
const resp = await response.json()
|
const resp = await response.json()
|
||||||
console.log("server response:", resp)
|
console.log("server response:", resp)
|
||||||
|
let cred = resp;
|
||||||
|
if (Array.isArray(resp) && resp.length > 0) {
|
||||||
|
cred = await showCredentialSelectionPopup(resp);
|
||||||
|
}
|
||||||
const credential = {
|
const credential = {
|
||||||
id: resp.id,
|
id: cred.id,
|
||||||
type: resp.type,
|
type: cred.type,
|
||||||
rawId: b64ab(resp.rawId),
|
rawId: b64ab(cred.rawId),
|
||||||
response: {
|
response: {
|
||||||
authenticatorData: b64ab(resp.response.authenticatorData),
|
authenticatorData: b64ab(cred.response.authenticatorData),
|
||||||
clientDataJSON: b64ab(resp.response.clientDataJSON),
|
clientDataJSON: b64ab(cred.response.clientDataJSON),
|
||||||
signature: b64ab(resp.response.signature)
|
signature: b64ab(cred.response.signature)
|
||||||
},
|
},
|
||||||
getClientExtensionResults: () => { return {} }
|
getClientExtensionResults: () => { return {} }
|
||||||
}
|
}
|
||||||
if (resp.response.userHandle) {
|
if (cred.response.userHandle) {
|
||||||
credential.response.userHandle = b64ab(resp.response.userHandle);
|
credential.response.userHandle = b64ab(cred.response.userHandle);
|
||||||
}
|
}
|
||||||
console.log(credential)
|
console.log(credential)
|
||||||
return credential;
|
return credential;
|
||||||
|
|||||||
Reference in New Issue
Block a user