Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions extension/authenticator.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ window.authnTools = window.authnTools || {};
const initAuthenticator = async () => {
const authenticator = new window.AuthnDevice();
// Override storage handler to use chrome.storage.local
authenticator.handleStorage = function (data) {
if (data) {
authenticator.handleStorage = async function (data = null) {
if (data !== null) {
// Save mode - return a promise or handle async
return new Promise((resolve, reject) => {
chrome.storage.local.set({ 'system_credentials': data }, () => {
console.log('Credentials saved to local storage');
resolve(data);
});
});
await chrome.storage.local.set({ 'system_credentials': data }
);
console.log('Credentials saved to local storage');
return data;
} else {
//const result = await chrome.storage.local.get('system_credentials');
//return result.system_credentials || [];
return this.storage;
}
};
Expand Down Expand Up @@ -61,6 +61,7 @@ const initAuthenticator = async () => {
authenticator.legacyMasterkeySalt = legacySalt.buffer;
console.log('[Auth] Legacy salt fallback initialized (16 zeros).');

// authenticator.storage = result.system_credentials || [];
if (result.system_credentials) authenticator.storage = result.system_credentials;
authenticator.debugLogging = result['option@debugLogging'] === true;
return authenticator;
Expand Down Expand Up @@ -142,9 +143,12 @@ const handleMessage = async (request, sender, sendResponse) => {
// So we need to manually ensure we save "authenticator.storage" if it changed?
// UNLESS we explicit save here.

debugLog('[Auth] Manually ensuring storage save...');
await new Promise(r => chrome.storage.local.set({ 'system_credentials': deviceInstance.storage }, r));
debugLog('[Auth] Manual save complete.');
if (deviceInstance.storage) {
debugLog('[Auth] Manually ensuring storage save...');
await new Promise(r => chrome.storage.local.set({ 'system_credentials': deviceInstance.storage }, r));
debugLog('[Auth] Manual save complete.');
}

} else if (request.type === 'get' || request.authn === 'get') {
debugLog('[Auth] Get Options (Raw):', request.options);

Expand Down
110 changes: 94 additions & 16 deletions extension/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,98 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {

if (message.type === 'authenticator_ready') {
// The popup is open and ready. Send the pending request.
console.log("AUTHENTICATOR READY");
if (pendingRequest) {
chrome.runtime.sendMessage(pendingRequest);
// pendingRequest = null; // Keep it until completion? No, simple flow.
}
return;
}

// Message from the authenticator popup (completion)
if (message.status === 'completed' || message.status === 'error') {
// Forward to the tab that requested it
if (message.status === "completed" || message.status === "error") {

// console.log(
// "FULL COMPLETION MESSAGE:",
// message
// );

let credential = null;

if (message.credential) {
try {
credential = JSON.parse(message.credential);
console.log("PARSED CREDENTIAL:", credential);
} catch (e) {
console.error("FAILED TO PARSE CREDENTIAL:", e);
}
}

//
// Debug credential payload
//
if (message.credential) {

try {
let credential = JSON.parse(message.credential);

console.log(
"PARSED CREDENTIAL:",
credential
);

// rawId
if (credential.rawId?.data) {
let rawId = new Uint8Array(credential.rawId.data);
console.log("FORWARDED RAW ID:",rawId.byteLength,rawId);
}

// authenticatorData
if (
credential.response?.authenticatorData?.data
) {

let authData = new Uint8Array(credential.response.authenticatorData.data);
console.log("FORWARDED AUTHDATA:",authData.byteLength);
}

// signature
if (credential.response?.signature?.data) {
let signature =
new Uint8Array(credential.response.signature.data
);

console.log("FORWARDED SIGNATURE:",signature.byteLength);

console.log(
"SIGNATURE HEX:",
Array.from(signature)
.map(
b =>
b.toString(16)
.padStart(2,"0")
)
.join("")
);
}

// userHandle
if (
credential.response?.userHandle?.data
) {

let userHandle =
new Uint8Array(
credential.response.userHandle.data
);

console.log("FORWARDED USER HANDLE:",userHandle.byteLength);
}


}
catch(e) {console.error("FAILED TO PARSE CREDENTIAL:",e);
}
}

// If we have a stored tab ID from the pending request, use it.
if (pendingRequest && pendingRequest.requestingTabId) {
Expand All @@ -31,19 +113,14 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
...message,
extensionResponse: true
});
// Clear pending request after completion?
// Clear pending request after completion?
// Maybe wait a bit or clear it now. Let's clear it to be clean.
// pendingRequest = null;
// Clear request after completion
pendingRequest = null;
} else {
// Fallback: Query active tab (less reliable if popup is focused or user switched tabs)
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs.length > 0) {
chrome.tabs.sendMessage(tabs[0].id, {
...message,
extensionResponse: true // Flag to identify it
});
}
});
// Do not fallback to active tab.
// The active tab may not be the tab that initiated WebAuthn.
console.warn("No requesting tab stored");
}
return;
}
Expand All @@ -57,15 +134,16 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
pendingRequest.requestingTabId = sender.tab.id;
}

// Open the popup
// Open the authenticator popup
chrome.windows.create({
url: "authenticator.html",
type: "popup",
width: 400,
height: 600,
focused: true
}, (window) => {
popupWindowId = window.id;
if(window)
popupWindowId = window.id;
});

sendResponse({ started: true });
Expand Down
Loading