summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPawel Zelawski <pawel.zelawski@outlook.com>2025-04-09 20:18:15 +0200
committerPawel Zelawski <pawel.zelawski@outlook.com>2025-04-09 20:18:15 +0200
commita45bcd5f84b2e7be982e170aa31f64afac61a337 (patch)
tree7050422e138b7ffdc75222639a9038ed4a457dfd
parent14d86ef2043828ad624f2bded91de838c3a13fcd (diff)
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.
-rw-r--r--README.md10
-rw-r--r--examples/generate-uri.ts72
-rw-r--r--examples/verify-callback-example.ts92
-rw-r--r--src/digiid.ts4
-rw-r--r--tsconfig.json6
5 files changed, 183 insertions, 1 deletions
diff --git a/README.md b/README.md
index 155aa09..6fce048 100644
--- a/README.md
+++ b/README.md
@@ -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