Skip to content

Commit e96cf06

Browse files
committed
simplified
1 parent a4f664d commit e96cf06

File tree

2 files changed

+47
-147
lines changed

2 files changed

+47
-147
lines changed

example_backend.js

Lines changed: 36 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -40,37 +40,7 @@ const start = async function (identityId) {
4040
};
4141

4242
// Public: Verify the authentication by checking the score and session data
43-
const verifyAuthentication = async function (interviewId, token, candidate) {
44-
const session = await getSession(interviewId);
45-
46-
// Prevents usage of session that doesn't exist.
47-
if (!session) {
48-
return {
49-
// Detailed debug message, in production you might want to avoid exposing internal details.
50-
message: "No session found for interviewId " + interviewId,
51-
valid: false,
52-
};
53-
}
54-
55-
// Prevents reuse of the same session.
56-
if (session.status !== "pending") {
57-
return {
58-
// Detailed debug message, in production you might want to avoid exposing internal details.
59-
message: "Session already used for interviewId " + interviewId,
60-
valid: false,
61-
};
62-
}
63-
64-
// Prevents usage of token from another interviewId.
65-
if (session.token !== token) {
66-
// Mark the session as rejected.
67-
await updateSession(interviewId, "rejected");
68-
return {
69-
// Detailed debug message, in production you might want to avoid exposing internal details.
70-
message: "Token mismatch for interviewId " + interviewId,
71-
valid: false,
72-
};
73-
}
43+
const getResults = async function (interviewId, token, candidate) {
7444

7545
// Prevents usage of candidate that doesn't match the identityId stored in session.
7646
if (session.identityId !== candidate) {
@@ -79,77 +49,71 @@ const verifyAuthentication = async function (interviewId, token, candidate) {
7949
return {
8050
// Detailed debug message, in production you might want to avoid exposing internal details.
8151
message: "identityId and candidate mismatch for interviewId " + interviewId,
82-
valid: false,
52+
isValid: false,
8353
};
8454
}
8555

86-
// Finishing the session stop it from being changed further and triggers score calculation and business rules.
87-
await finish(token); // Mark session as finished in Incode backend
56+
// Finishing the session triggers score calculation and business rules.
57+
await finishStatus(token); // Mark session as finished in Incode backend
58+
// Closing the session stop it from being changed, all /add/ endpoints will be rejected after this, and the score will be frozen.
59+
await setStatusClosed(token); // Mark session as closed in Incode backend
60+
8861

8962
let identityId, scoreStatus;
9063
try {
9164
// At this point we already verified that the token matches, but
9265
// to be clear about our intentions, we use the token stored in the
9366
// database to get the identityId and compare it with the candidate.
94-
const scoreResponse = await getScore(session.token);
67+
const scoreResponse = await getScore(token);
9568
identityId = scoreResponse.authentication.identityId;
9669
scoreStatus = scoreResponse.overall.status;
9770
} catch (e) {
98-
// Mark the session as rejected.
99-
await updateSession(interviewId, "rejected");
10071
// If there is an error communicating with API, we consider validation failed.
10172
return {
10273
// Detailed debug message, in production you might want to avoid exposing internal details.
10374
message: "Error validating authentication for interviewId " + interviewId + ": " + e.message,
104-
valid: false,
75+
isValid: false,
10576
};
10677
}
10778

10879
// renderFaceAuth returns candidate, which should match identityId from score,
10980
// this prevents tampering of the identityId in the frontend.
11081
if (identityId !== candidate) {
111-
// Mark the session as rejected.
112-
await updateSession(interviewId, "rejected");
11382
return {
11483
// Detailed debug message, in production you might want to avoid exposing internal details.
11584
message: "Session data doesn't match for interviewId " + interviewId,
116-
valid: false,
85+
isValid: false,
11786
};
11887
}
11988

12089
// If backend score overall status is not OK, validation fails.
12190
if (scoreStatus !== "OK") {
122-
// Mark the session as rejected.
123-
await updateSession(interviewId, "rejected");
12491
return {
12592
// Detailed debug message, in production you might want to avoid exposing internal details.
12693
message: "Face Validation failed for interviewId " + interviewId,
127-
valid: false,
94+
isValid: false,
12895
};
12996
}
13097

131-
// Mark the session as approved since all checks passed.
132-
await updateSession(interviewId, "approved");
133-
13498
// Only valid if all checks passed, we return the identityId that was validated.
13599
return {
136100
// Detailed debug message, in production you might want to avoid exposing internal details.
137101
message: "Face Validation succeeded for interviewId " + interviewId,
138-
valid: true,
102+
isValid: true,
139103
identityId: identityId,
140104
};
141105
};
142106

143107
// Private: Calls Incode's `omni/finish-status` API mark the session as finished
144-
const finish = async function (token) {
108+
const finishStatus = async function (token) {
145109
const url = `${apiurl}/omni/finish-status`;
146110

147111
let sessionHeaders = { ...defaultHeader };
148112
sessionHeaders["X-Incode-Hardware-Id"] = token;
149113

150114
let response;
151115
try {
152-
response = await fetch(url, { method: "GET", headers: sessionHeaders });
116+
response = await fetch(url, { method: "POST", body: "{}", headers: sessionHeaders });
153117
if (!response.ok) {
154118
throw new Error("Request failed with code " + response.status);
155119
}
@@ -160,6 +124,27 @@ const finish = async function (token) {
160124
return { redirectionUrl, action };
161125
};
162126

127+
// Private: Calls Incode's `omni/session/status/set?action=Closed` API to close the session
128+
const setStatusClosed = async function (token) {
129+
const url = `${apiurl}/omni/session/status/set?action=Closed`;
130+
131+
let sessionHeaders = { ...defaultHeader };
132+
sessionHeaders["X-Incode-Hardware-Id"] = token;
133+
134+
let response;
135+
try {
136+
response = await fetch(url, { method: "POST", body: "{}", headers: sessionHeaders });
137+
if (!response.ok) {
138+
throw new Error("Request failed with code " + response.status);
139+
}
140+
} catch (e) {
141+
throw new Error("HTTP Post Error: " + e.message);
142+
}
143+
const results = await response.json();
144+
console.log({results});
145+
return results;
146+
};
147+
163148
// Private: Call Incode's `omni/get/score` API to retrieve the score for the session
164149
const getScore = async function (token) {
165150
const url = `${apiurl}/omni/get/score`;
@@ -226,92 +211,7 @@ const getScore = async function (token) {
226211
return score;
227212
};
228213

229-
/** Helper functions for sessions saving and retrieval from IndexedDB,
230-
* in production this should be handled with your backend or secure storage */
231-
232-
// Local database helper functions using IndexedDB
233-
const DB_NAME = "AuthenticationDB";
234-
const DB_VERSION = 1;
235-
const STORE_NAME = "sessions";
236-
237-
// Initialize IndexedDB
238-
function initDB() {
239-
return new Promise((resolve, reject) => {
240-
const request = indexedDB.open(DB_NAME, DB_VERSION);
241-
242-
request.onerror = () => reject(request.error);
243-
request.onsuccess = () => resolve(request.result);
244214

245-
request.onupgradeneeded = (event) => {
246-
const db = event.target.result;
247-
if (!db.objectStoreNames.contains(STORE_NAME)) {
248-
const objectStore = db.createObjectStore(STORE_NAME, { keyPath: "interviewId" });
249-
objectStore.createIndex("interviewId", "interviewId", { unique: true });
250-
}
251-
};
252-
});
253-
}
254-
255-
// Read a specific session from IndexedDB by interviewId
256-
async function getSession(interviewId) {
257-
const db = await initDB();
258-
return new Promise((resolve, reject) => {
259-
const transaction = db.transaction([STORE_NAME], "readonly");
260-
const objectStore = transaction.objectStore(STORE_NAME);
261-
const request = objectStore.get(interviewId);
262-
263-
request.onsuccess = () => resolve(request.result);
264-
request.onerror = () => reject(request.error);
265-
});
266-
}
267-
268-
// Add a new session to the database
269-
async function addSession(interviewId, token, identityId) {
270-
const db = await initDB();
271-
return new Promise((resolve, reject) => {
272-
const transaction = db.transaction([STORE_NAME], "readwrite");
273-
const objectStore = transaction.objectStore(STORE_NAME);
274-
const session = {
275-
interviewId,
276-
token,
277-
identityId,
278-
status: "pending",
279-
timestamp: new Date().toISOString(),
280-
};
281-
const request = objectStore.add(session);
282-
283-
request.onsuccess = () => resolve(session);
284-
request.onerror = () => reject(request.error);
285-
});
286-
}
287-
288-
// Update validation status for a session
289-
async function updateSession(interviewId, status) {
290-
291-
if (status !== "rejected" && status !== "approved") {
292-
throw new Error("Invalid status. Must be 'rejected' or 'approved'.");
293-
}
294-
295-
const db = await initDB();
296-
return new Promise((resolve, reject) => {
297-
const transaction = db.transaction([STORE_NAME], "readwrite");
298-
const objectStore = transaction.objectStore(STORE_NAME);
299-
const getRequest = objectStore.get(interviewId);
300-
301-
getRequest.onsuccess = () => {
302-
const session = getRequest.result;
303-
if (session) {
304-
session.status = status;
305-
const updateRequest = objectStore.put(session);
306-
updateRequest.onsuccess = () => resolve(session);
307-
updateRequest.onerror = () => reject(updateRequest.error);
308-
} else {
309-
resolve(null);
310-
}
311-
};
312-
getRequest.onerror = () => reject(getRequest.error);
313-
});
314-
}
315215

316-
const exampleBackend = { start, verifyAuthentication }
216+
const exampleBackend = { start, getResults }
317217
export default exampleBackend;

main.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,35 +60,35 @@ function finishAuthentication(response) {
6060
container.innerHTML = `
6161
<h1>Authentication Process Finished</h1>
6262
<p><strong>Candidate:</strong> ${candidate}</p>
63-
<button id="verify-authentication-btn">Verify Authentication</button>
63+
<button id="get-results-btn">Get Results</button>
6464
`;
65-
document.getElementById("verify-authentication-btn").addEventListener("click", verifyAuthentication);
65+
document.getElementById("get-results-btn").addEventListener("click", getResults);
6666
}
6767

6868
// 4.- Verify the authentication against the score
69-
async function verifyAuthentication() {
70-
console.log("Verifying authentication for candidate:", candidate);
69+
async function getResults() {
70+
console.log("Getting results of the authentication");
7171
try {
72-
const validationResult = await exampleBackend.verifyAuthentication(
72+
const results = await exampleBackend.getResults(
7373
incodeSession.interviewId,
7474
incodeSession.token,
7575
candidate,
7676
);
77-
console.log("Validation result:", validationResult);
77+
console.log("Result:", results);
7878

7979
const container = document.getElementById("finish-container");
8080
container.innerHTML += `
8181
<hr>
8282
<h2>Authentication Verification</h2>
8383
<p><strong>Interview ID:</strong> ${incodeSession.interviewId}</p>
8484
<p><strong>Candidate:</strong> ${candidate}</p>
85-
<p><strong>Identity ID:</strong> ${validationResult.identityId || "N/A"}</p>
86-
<p><strong>Message:</strong> ${validationResult.message}</p>
87-
<p><strong>Authentication Valid:</strong> <span style="color: ${validationResult.valid ? "green" : "red"}; font-weight: bold;">${
88-
validationResult.valid ? "✓ VALID" : "✗ INVALID"
85+
<p><strong>Identity ID:</strong> ${results.identityId || "N/A"}</p>
86+
<p><strong>Message:</strong> ${results.message}</p>
87+
<p><strong>Authentication Valid:</strong> <span style="color: ${results.isValid ? "green" : "red"}; font-weight: bold;">${
88+
results.isValid ? "✓ VALID" : "✗ INVALID"
8989
}</span></p>
9090
`;
91-
document.getElementById("verify-authentication-btn").addEventListener("click", verifyAuthentication);
91+
document.getElementById("get-results-btn").addEventListener("click", getResults);
9292
} catch (e) {
9393
showError(e);
9494
}

0 commit comments

Comments
 (0)