feat(fpagent): authenticate the wizard's a2loft calls with the session token
The fingerprint wizard's staff-lookup and fingerprint-save proxies forwarded the page's OTP with the session phone. a2loft resolves that phone against the domain being addressed, so an operator who holds only capture_biometric was rejected unless they were a domain super-user. The cropper already saves with the session token. - tools/server.js: both a2loft proxies send Authorization: Bearer <session token>, no phone/otp; validateProxy drops the OTP and phone checks. - tools/public/assets/fp: both OTP fields, otpLookup/otpSave state, request params and resets removed; canLookup/canSave no longer gate on OTP. - Tests assert the Bearer header, no query auth, no OTP field in the served page, and both gates without a credential (66/66 pass). - README and Help page updated. Requires the a2loft fingerprint-token-auth change deployed first. OpenSpec change: fingerprint-token-auth.
This commit is contained in:
@@ -25,8 +25,6 @@ Vue.config.ignoredElements = [/^cds-/];
|
||||
agent: { connected: false, version: '', captureAgentId: '', available: null, device: '' },
|
||||
domain: '',
|
||||
reference: '',
|
||||
otpLookup: '',
|
||||
otpSave: '',
|
||||
staff: null,
|
||||
busy: { lookup: false, save: false },
|
||||
refreshing: false,
|
||||
@@ -49,10 +47,10 @@ Vue.config.ignoredElements = [/^cds-/];
|
||||
this.fingers['right-index-finger'].status === 'done';
|
||||
},
|
||||
canLookup: function () {
|
||||
return !!(this.domain && this.reference && this.otpLookup) && !this.busy.lookup;
|
||||
return !!(this.domain && this.reference) && !this.busy.lookup;
|
||||
},
|
||||
canSave: function () {
|
||||
return this.bothCaptured && !!this.otpSave && !this.busy.save;
|
||||
return this.bothCaptured && !this.busy.save;
|
||||
},
|
||||
refreshUnlocksAt: function () {
|
||||
var ttl = (this.session && this.session.domainCacheTtlMs) || 5 * 60 * 1000;
|
||||
@@ -296,9 +294,7 @@ Vue.config.ignoredElements = [/^cds-/];
|
||||
if (!this.canLookup) return;
|
||||
this.busy.lookup = true;
|
||||
axios.post(
|
||||
'/api/' + encodeURIComponent(this.domain) + '/staff/' + encodeURIComponent(this.reference),
|
||||
null,
|
||||
{ params: { otp: this.otpLookup } }
|
||||
'/api/' + encodeURIComponent(this.domain) + '/staff/' + encodeURIComponent(this.reference)
|
||||
).then(function (r) {
|
||||
if (!r.data.ok) {
|
||||
self.showNotif('error', 'Not found', 'Operation failed. ' + (r.data.message || '') + ' (reference ' + self.reference + ')');
|
||||
@@ -322,8 +318,7 @@ Vue.config.ignoredElements = [/^cds-/];
|
||||
});
|
||||
axios.post(
|
||||
'/api/' + encodeURIComponent(this.domain) + '/staff/' + encodeURIComponent(this.reference) + '/fingerprints',
|
||||
{ fingerprints: fingerprints },
|
||||
{ params: { otp: this.otpSave } }
|
||||
{ fingerprints: fingerprints }
|
||||
).then(function (r) {
|
||||
if (r.data.ok) {
|
||||
self.showNotif('success', 'Enrollment saved',
|
||||
@@ -343,8 +338,6 @@ Vue.config.ignoredElements = [/^cds-/];
|
||||
newEnrollment: function () {
|
||||
this.staff = null;
|
||||
this.reference = '';
|
||||
this.otpLookup = '';
|
||||
this.otpSave = '';
|
||||
this.fingers = { 'right-thumb': newFinger(), 'right-index-finger': newFinger() };
|
||||
this.capturing = null;
|
||||
this.cancelling = false;
|
||||
|
||||
Reference in New Issue
Block a user