From a45bcd5f84b2e7be982e170aa31f64afac61a337 Mon Sep 17 00:00:00 2001 From: Pawel Zelawski Date: Wed, 9 Apr 2025 20:18:15 +0200 Subject: docs: Add README, usage examples, and example runner instructions - Create comprehensive README.md including: - Features, Installation (from GitHub), Usage examples (URI generation, callback verification), API Reference, Dependency status note, Testing instructions. - Review and confirm adequacy of TSDoc comments in source files. - Update README intro sentence and add explicit notes on required URL format. - Create `examples/` directory with runnable scripts: - `examples/generate-uri.ts` - `examples/verify-callback-example.ts` - Update signature verification helper (`_internalVerifySignature`) to use `createRequire` for CJS dependency loading in ESM context (required for examples). - Add "Running Examples" section to README with the correct `node --loader ts-node/esm` command. --- examples/generate-uri.ts | 72 +++++++++++++++++++++++++++++ examples/verify-callback-example.ts | 92 +++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 examples/generate-uri.ts create mode 100644 examples/verify-callback-example.ts (limited to 'examples') diff --git a/examples/generate-uri.ts b/examples/generate-uri.ts new file mode 100644 index 0000000..9aee864 --- /dev/null +++ b/examples/generate-uri.ts @@ -0,0 +1,72 @@ +// examples/generate-uri.ts + +// Import directly from src for running locally before publishing +// In a real project, you'd import from 'digiid-ts' after installing +// Revert extension, ts-node should handle this when configured +import { generateDigiIDUri, DigiIDError } from '../src/index'; + +console.log('--- DigiID URI Generation Example ---'); + +// --- Example 1: Secure Callback (HTTPS) --- +const secureOptions = { + callbackUrl: 'https://myapp.example.com/api/auth/digiid', +}; + +try { + const secureUri = generateDigiIDUri(secureOptions); + console.log('\nSecure URI (HTTPS):'); + console.log(` Callback: ${secureOptions.callbackUrl}`); + console.log(` Generated: ${secureUri}`); + // Typically, you would now generate a QR code from secureUri +} catch (error) { + console.error('Error generating secure URI:', (error as Error).message); +} + +// --- Example 2: Unsecure Callback (HTTP) for Testing --- +const unsecureOptions = { + callbackUrl: 'http://localhost:8080/dev/callback', + unsecure: true, // Must set this flag for http +}; + +try { + const unsecureUri = generateDigiIDUri(unsecureOptions); + console.log('\nUnsecure URI (HTTP) for testing:'); + console.log(` Callback: ${unsecureOptions.callbackUrl}`); + console.log(` Generated: ${unsecureUri}`); +} catch (error) { + console.error('Error generating unsecure URI:', (error as Error).message); +} + +// --- Example 3: Providing a Custom Nonce --- +const customNonceOptions = { + callbackUrl: 'https://anotherapp.com/verify', + nonce: 'my-unique-secret-nonce-per-request-12345' +}; + +try { + const customNonceUri = generateDigiIDUri(customNonceOptions); + console.log('\nURI with Custom Nonce:'); + console.log(` Callback: ${customNonceOptions.callbackUrl}`); + console.log(` Nonce: ${customNonceOptions.nonce}`); + console.log(` Generated: ${customNonceUri}`); +} catch (error) { + console.error('Error generating URI with custom nonce:', (error as Error).message); +} + +// --- Example 4: Invalid URL (Missing Scheme) --- +const invalidUrlOptions = { + callbackUrl: 'myapi.com/auth' // Missing https:// +}; + +console.log('\nAttempting URI with Invalid URL (expecting error):'); +try { + generateDigiIDUri(invalidUrlOptions as any); +} catch (error) { + if (error instanceof DigiIDError) { + console.log(` Caught expected DigiIDError: ${error.message}`); + } else { + console.error(' Caught unexpected error:', error); + } +} + +console.log('\n--- End of Generation Example ---'); diff --git a/examples/verify-callback-example.ts b/examples/verify-callback-example.ts new file mode 100644 index 0000000..c416d0a --- /dev/null +++ b/examples/verify-callback-example.ts @@ -0,0 +1,92 @@ +// examples/verify-callback-example.ts + +// Import directly from src for running locally before publishing +// In a real project, you'd import from 'digiid-ts' after installing +// Revert extension, ts-node should handle this when configured +import { verifyDigiIDCallback, DigiIDCallbackData, DigiIDError } from '../src/index'; + +console.log('--- DigiID Callback Verification Example ---'); + +// --- Mock Data & Setup --- + +// This would normally come from your session/database lookup based on the request +const EXPECTED_NONCE = '61616161616161616161616161616161'; // Matches default nonce from crypto mock +const EXPECTED_CALLBACK_URL = 'https://myapp.example.com/api/auth/digiid'; + +// This data would normally come from the POST request body sent by the wallet +const mockCallbackData: DigiIDCallbackData = { + address: 'D7dVskXFpH8gTgZG9sN3d6dPUbJtZfJ2Vc', // A syntactically valid address + // URI containing the expected callback and nonce + uri: `digiid://myapp.example.com/api/auth/digiid?x=${EXPECTED_NONCE}&u=0`, + // IMPORTANT: This is a placeholder signature! + // Real verification requires a valid signature generated by a wallet signing the URI. + // This example will likely fail signature verification if run against the real library, + // unless the underlying verify function is mocked/stubbed. + signature: 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiYw==', +}; + +// Verification options derived from our expected state +const verifyOptions = { + expectedCallbackUrl: EXPECTED_CALLBACK_URL, + expectedNonce: EXPECTED_NONCE, +}; + +// --- Simulation Function --- + +async function simulateVerification(data: DigiIDCallbackData, options: typeof verifyOptions) { + console.log('\nAttempting verification with:'); + console.log(` Address: ${data.address}`); + console.log(` URI: ${data.uri}`); + console.log(` Signature: ${data.signature.substring(0, 30)}...`); + console.log(` Expected URL: ${options.expectedCallbackUrl}`); + console.log(` Expected Nonce: ${options.expectedNonce}`); + + try { + const result = await verifyDigiIDCallback(data, options); + console.log('\nVerification Successful!'); + console.log(` Address Verified: ${result.address}`); + console.log(` Nonce Verified: ${result.nonce}`); + // In a real app: log user in, mark nonce as used, etc. + + } catch (error) { + if (error instanceof DigiIDError) { + console.error(`\nVerification Failed: ${error.message}`); + // In a real app: return 400 Bad Request + } else { + console.error('\nUnexpected Verification Error:', error); + // In a real app: return 500 Internal Server Error + } + } +} + +// --- Run Simulation --- + +// Simulate verifying the correct data (likely fails signature check without mocks) +// We wrap this in an async IIFE (Immediately Invoked Function Expression) +// to use await at the top level. +(async () => { + await simulateVerification(mockCallbackData, verifyOptions); + + // Example: Simulate a Nonce Mismatch + console.log('\n--- Simulating Nonce Mismatch ---'); + await simulateVerification( + mockCallbackData, + { ...verifyOptions, expectedNonce: 'DIFFERENT_NONCE' } + ); + + // Example: Simulate a URL Mismatch + console.log('\n--- Simulating URL Mismatch ---'); + await simulateVerification( + mockCallbackData, + { ...verifyOptions, expectedCallbackUrl: 'https://wrongsite.com/callback' } + ); + + // Example: Simulate missing signature + console.log('\n--- Simulating Missing Signature ---'); + await simulateVerification( + { ...mockCallbackData, signature: '' }, + verifyOptions + ); + + console.log('\n--- End of Verification Example ---'); +})(); -- cgit v1.2.3