diff options
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | examples/generate-uri.ts | 72 | ||||
-rw-r--r-- | examples/verify-callback-example.ts | 92 | ||||
-rw-r--r-- | src/digiid.ts | 4 | ||||
-rw-r--r-- | tsconfig.json | 6 |
5 files changed, 183 insertions, 1 deletions
@@ -131,6 +131,16 @@ app.post('/api/digiid/callback', async (req, res) => { (Refer to `src/types.ts` for detailed interface definitions) +## Running Examples + +Examples are available in the `examples/` directory. You can run them using `ts-node` via the Node.js loader: + +```bash +# Ensure ts-node is installed (npm install -D ts-node) +node --loader ts-node/esm examples/generate-uri.ts +node --loader ts-node/esm examples/verify-callback-example.ts +``` + ## Dependencies This library currently uses a specific commit from a fork of `bitcore-message` (`digicontributer/bitcore-message`) for signature verification, matching the original `digiid-js` library. This is an older dependency. 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 ---'); +})(); diff --git a/src/digiid.ts b/src/digiid.ts index 8b1dc07..363a82f 100644 --- a/src/digiid.ts +++ b/src/digiid.ts @@ -1,4 +1,6 @@ import { randomBytes } from 'crypto'; +// Import createRequire for CJS dependencies in ESM +import { createRequire } from 'module'; import { DigiIDUriOptions, DigiIDError, @@ -20,6 +22,8 @@ export async function _internalVerifySignature( address: string, signature: string ): Promise<boolean> { + // Create a require function scoped to this module + const require = createRequire(import.meta.url); // eslint-disable-next-line @typescript-eslint/no-var-requires const Message = require('digibyte-message'); try { diff --git a/tsconfig.json b/tsconfig.json index 3fbb53f..1f39a7a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,5 +36,9 @@ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, "include": ["src/**/*.ts"], /* Specifies a list of files to be included in compilation */ - "exclude": ["node_modules", "dist", "examples", "**/*.test.ts"] /* Specifies a list of files to be excluded from compilation */ + "exclude": ["node_modules", "dist", "examples", "**/*.test.ts"], /* Specifies a list of files to be excluded from compilation */ + "ts-node": { + "esm": true, + "experimentalSpecifierResolution": "node" + } }
\ No newline at end of file |