Skip to content

Commit

Permalink
Fetch-timeout (#269)
Browse files Browse the repository at this point in the history
Signed-off-by: Mirko Mollik <[email protected]>
Signed-off-by: Mirko Mollik <[email protected]>
  • Loading branch information
cre8 authored Jan 23, 2025
1 parent 5e64551 commit 76d1b7b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 32 deletions.
13 changes: 2 additions & 11 deletions packages/sd-jwt-vc/src/sd-jwt-vc-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,10 @@ export class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
* @returns
*/
private async fetch<T>(url: string, integrity?: string): Promise<T> {
const controller = new AbortController();
const timeoutId = setTimeout(
() => controller.abort(),
this.userConfig.timeout ?? 10000,
);

try {
const response = await fetch(url, {
signal: controller.signal,
signal: AbortSignal.timeout(this.userConfig.timeout ?? 10000),
});

if (!response.ok) {
const errorText = await response.text();
throw new Error(
Expand All @@ -187,12 +180,10 @@ export class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
await this.validateIntegrity(response.clone(), url, integrity);
return response.json() as Promise<T>;
} catch (error) {
if (error instanceof DOMException && error.name === 'AbortError') {
if ((error as Error).name === 'TimeoutError') {
throw new Error(`Request to ${url} timed out`);
}
throw error;
} finally {
clearTimeout(timeoutId);
}
}

Expand Down
69 changes: 48 additions & 21 deletions packages/sd-jwt-vc/src/test/vct.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { digest, generateSalt } from '@sd-jwt/crypto-nodejs';
import type { DisclosureFrame, Signer, Verifier } from '@sd-jwt/types';
import { describe, test, beforeAll, afterAll } from 'vitest';
import { describe, test, beforeAll, afterAll, expect } from 'vitest';
import { SDJwtVcInstance } from '..';
import type { SdJwtVcPayload } from '../sd-jwt-vc-payload';
import Crypto from 'node:crypto';
Expand Down Expand Up @@ -41,7 +41,7 @@ const restHandlers = [
};
return HttpResponse.json(res);
}),
http.get('http://exmaple.com/example', () => {
http.get('http://example.com/example', () => {
const res: TypeMetadataFormat = {
vct: 'http://example.com/example',
name: 'ExampleCredentialType',
Expand All @@ -53,6 +53,13 @@ const restHandlers = [
};
return HttpResponse.json(res);
}),
http.get('http://example.com/timeout', () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(HttpResponse.json({}));
}, 10000);
});
}),
];

//this value could be generated on demand to make it easier when changing the values
Expand All @@ -62,7 +69,7 @@ const vctIntegrity =
const server = setupServer(...restHandlers);

const iss = 'ExampleIssuer';
const vct = 'http://exmaple.com/example';
const vct = 'http://example.com/example';
const iat = new Date().getTime() / 1000;

const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
Expand All @@ -84,31 +91,33 @@ const createSignerVerifier = () => {
};

describe('App', () => {
const { signer, verifier } = createSignerVerifier();

const sdjwt = new SDJwtVcInstance({
signer,
signAlg: 'EdDSA',
verifier,
hasher: digest,
hashAlg: 'sha-256',
saltGenerator: generateSalt,
loadTypeMetadataFormat: true,
timeout: 1000,
});

const claims = {
firstname: 'John',
};
const disclosureFrame = {
_sd: ['firstname'],
};

beforeAll(() => server.listen({ onUnhandledRequest: 'warn' }));

afterAll(() => server.close());

afterEach(() => server.resetHandlers());

test('VCT Validation', async () => {
const { signer, verifier } = createSignerVerifier();
const sdjwt = new SDJwtVcInstance({
signer,
signAlg: 'EdDSA',
verifier,
hasher: digest,
hashAlg: 'sha-256',
saltGenerator: generateSalt,
loadTypeMetadataFormat: true,
});

const claims = {
firstname: 'John',
};
const disclosureFrame = {
_sd: ['firstname'],
};

const expectedPayload: SdJwtVcPayload = {
iat,
iss,
Expand All @@ -124,5 +133,23 @@ describe('App', () => {
await sdjwt.verify(encodedSdjwt);
});

test('VCT Validation with timeout', async () => {
const vct = 'http://example.com/timeout';
const expectedPayload: SdJwtVcPayload = {
iat,
iss,
vct,
...claims,
};
const encodedSdjwt = await sdjwt.issue(
expectedPayload,
disclosureFrame as unknown as DisclosureFrame<SdJwtVcPayload>,
);

expect(sdjwt.verify(encodedSdjwt)).rejects.toThrowError(
`Request to ${vct} timed out`,
);
});

//TODO: we need tests with an embedded schema, extended and maybe also to test the errors when schema information is not available or the integrity is not valid
});

0 comments on commit 76d1b7b

Please sign in to comment.