@usemona/attest-backend-sdk
Version:
Mona Attest Backend SDK - Secure server-side verification for cryptographic attestations and digital signatures. Provides robust signature validation, user verification, and enterprise-grade security for Node.js applications.
125 lines (124 loc) • 5.16 kB
JavaScript
export class AttestBackendSDK {
constructor(config = {}) {
// Use provided URL or default
this.apiUrl = config.apiUrl || 'https://api.attest.ng';
console.log('🔧 AttestBackendSDK Constructor:', {
apiUrl: this.apiUrl
});
}
/**
* Verify an attestation token against the original API call
*/
async verifyAttestation(attestationToken, originalAPICall) {
try {
// Step 1: Extract session ID and signature from token
const { sessionId, signatureBase64 } = this.parseAttestationToken(attestationToken);
// Step 2: Pass everything to Mona Attest backend for verification
return await this.verifyWithAttest(sessionId, signatureBase64, originalAPICall);
}
catch (error) {
return {
verified: false,
error: error instanceof Error ? error.message : 'Verification failed'
};
}
}
// ============================================================================
// PRIVATE HELPER METHODS
// ============================================================================
/**
* Verify attestation by calling Mona Attest backend with original API call data
*/
async verifyWithAttest(sessionId, signatureBase64, originalAPICall) {
try {
// Parse the signature data back to the format expected by complete-attest
const signatureData = JSON.parse(atob(signatureBase64));
// Create assertion response in the format expected by Mona Attest backend
const assertionResponse = {
id: signatureData.credentialId,
rawId: signatureData.credentialId, // Use same as id for compatibility
type: signatureData.type || 'public-key',
response: {
authenticatorData: signatureData.authenticatorData,
clientDataJSON: signatureData.clientDataJSON,
signature: signatureData.signature,
userHandle: signatureData.userHandle
}
};
const completeAttestUrl = `${this.apiUrl}/api/passkey/complete-attest`;
const response = await fetch(completeAttestUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Attestation-Session': sessionId
},
body: JSON.stringify({
assertionResponse,
// Pass original API call data for independent verification by Mona Attest backend
originalAPICall: {
method: originalAPICall.method,
uri: originalAPICall.uri,
body: originalAPICall.body,
headers: originalAPICall.headers
}
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Verification API failed: ${response.status} ${response.statusText} - ${errorText}`);
}
const verificationResult = await response.json();
if (verificationResult.success && verificationResult.verified) {
return {
verified: true,
originalPayload: originalAPICall.body,
signatureData: verificationResult.signedPayload,
keyId: verificationResult.keyId,
attestationId: verificationResult.attestationId,
timestamp: verificationResult.timestamp
};
}
else {
return {
verified: false,
error: verificationResult.message || 'Signature verification failed'
};
}
}
catch (error) {
return {
verified: false,
error: error instanceof Error ? error.message : 'Verification failed'
};
}
}
/**
* Parse attestation token to extract session ID and signature
*/
parseAttestationToken(attestationToken) {
try {
if (!attestationToken || typeof attestationToken !== 'string') {
throw new Error('Invalid attestation token format');
}
// Attestation token format: "sessionId.signatureBase64"
const parts = attestationToken.split('.');
if (parts.length !== 2) {
throw new Error('Invalid attestation token format - expected sessionId.signature');
}
const [sessionId, signatureBase64] = parts;
if (!sessionId || !signatureBase64) {
throw new Error('Invalid attestation token - missing sessionId or signature');
}
return { sessionId, signatureBase64 };
}
catch (error) {
throw error;
}
}
/**
* Get API URL
*/
getApiUrl() {
return this.apiUrl;
}
}