javascript-solid-server 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +8 -1
- package/package.json +2 -1
- package/src/auth/nostr.js +197 -0
- package/src/auth/token.js +13 -1
- package/src/handlers/container.js +62 -46
- package/src/idp/accounts.js +62 -12
- package/src/idp/index.js +11 -0
- package/src/idp/interactions.js +109 -10
- package/src/idp/views.js +62 -2
- package/src/wac/checker.js +3 -3
- package/src/wac/parser.js +25 -8
- package/test/idp.test.js +0 -12
- package/test/wac.test.js +27 -8
- package/test-data-idp-accounts/.idp/accounts/_email_index.json +1 -1
- package/test-data-idp-accounts/.idp/accounts/_username_index.json +3 -0
- package/test-data-idp-accounts/.idp/accounts/_webid_index.json +1 -1
- package/test-data-idp-accounts/.idp/accounts/ba3591b1-4653-4c64-9661-57dc355e5acc.json +10 -0
- package/test-data-idp-accounts/.idp/keys/jwks.json +8 -8
- package/test-nostr-acl.js +144 -0
- package/test-nostr-auth.js +114 -0
- package/test-data-idp-accounts/.idp/accounts/00f5d7c4-1da9-4e68-92c9-2b931f7c5750.json +0 -9
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test script for Nostr NIP-98 authentication
|
|
3
|
+
*
|
|
4
|
+
* Usage: node test-nostr-auth.js
|
|
5
|
+
*
|
|
6
|
+
* This script:
|
|
7
|
+
* 1. Generates a Nostr keypair
|
|
8
|
+
* 2. Creates a NIP-98 auth event
|
|
9
|
+
* 3. Makes authenticated request to JSS
|
|
10
|
+
* 4. Verifies the did:nostr identity is recognized
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { generateSecretKey, getPublicKey, finalizeEvent } from 'nostr-tools';
|
|
14
|
+
import { getToken } from 'nostr-tools/nip98';
|
|
15
|
+
|
|
16
|
+
const BASE_URL = process.env.TEST_URL || 'http://localhost:4000';
|
|
17
|
+
|
|
18
|
+
async function main() {
|
|
19
|
+
console.log('=== Nostr NIP-98 Authentication Test ===\n');
|
|
20
|
+
|
|
21
|
+
// Generate a new keypair
|
|
22
|
+
const sk = generateSecretKey();
|
|
23
|
+
const pk = getPublicKey(sk);
|
|
24
|
+
|
|
25
|
+
console.log('1. Generated keypair');
|
|
26
|
+
console.log(` Public key: ${pk}`);
|
|
27
|
+
console.log(` did:nostr: did:nostr:${pk}\n`);
|
|
28
|
+
|
|
29
|
+
// Create NIP-98 token for GET request to a public resource
|
|
30
|
+
const testUrl = `${BASE_URL}/`;
|
|
31
|
+
const method = 'GET';
|
|
32
|
+
|
|
33
|
+
console.log(`2. Creating NIP-98 token for ${method} ${testUrl}`);
|
|
34
|
+
|
|
35
|
+
const token = await getToken(testUrl, method, (event) => finalizeEvent(event, sk));
|
|
36
|
+
|
|
37
|
+
console.log(` Token length: ${token.length} chars\n`);
|
|
38
|
+
|
|
39
|
+
// Make authenticated request
|
|
40
|
+
console.log('3. Making authenticated request...');
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(testUrl, {
|
|
44
|
+
method,
|
|
45
|
+
headers: {
|
|
46
|
+
'Authorization': `Nostr ${token}`,
|
|
47
|
+
'Accept': 'application/json'
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(` Status: ${response.status} ${response.statusText}`);
|
|
52
|
+
|
|
53
|
+
// Check headers for any auth info
|
|
54
|
+
const wwwAuth = response.headers.get('www-authenticate');
|
|
55
|
+
if (wwwAuth) {
|
|
56
|
+
console.log(` WWW-Authenticate: ${wwwAuth}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// For a protected resource, we'd check if access was granted
|
|
60
|
+
// For now, just verify the request went through
|
|
61
|
+
if (response.ok) {
|
|
62
|
+
console.log(' Request succeeded!\n');
|
|
63
|
+
} else {
|
|
64
|
+
const body = await response.text();
|
|
65
|
+
console.log(` Response: ${body.slice(0, 200)}\n`);
|
|
66
|
+
}
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error(` Error: ${err.message}\n`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Test with a protected resource (if exists)
|
|
72
|
+
console.log('4. Testing access to a container...');
|
|
73
|
+
|
|
74
|
+
const containerUrl = `${BASE_URL}/demo/public/`;
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const containerToken = await getToken(containerUrl, 'GET', (event) => finalizeEvent(event, sk));
|
|
78
|
+
|
|
79
|
+
const response = await fetch(containerUrl, {
|
|
80
|
+
headers: {
|
|
81
|
+
'Authorization': `Nostr ${containerToken}`,
|
|
82
|
+
'Accept': 'text/turtle'
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
console.log(` ${containerUrl}`);
|
|
87
|
+
console.log(` Status: ${response.status} ${response.statusText}`);
|
|
88
|
+
|
|
89
|
+
if (response.status === 200) {
|
|
90
|
+
console.log(' Container accessible with Nostr auth!');
|
|
91
|
+
} else if (response.status === 403) {
|
|
92
|
+
console.log(' 403 Forbidden - auth worked but no ACL grant for did:nostr');
|
|
93
|
+
console.log(` (Add did:nostr:${pk} to ACL to grant access)`);
|
|
94
|
+
} else if (response.status === 404) {
|
|
95
|
+
console.log(' 404 Not Found - container does not exist');
|
|
96
|
+
}
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.error(` Error: ${err.message}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log('\n=== Test Complete ===');
|
|
102
|
+
console.log('\nTo grant this identity access, add to an ACL file:');
|
|
103
|
+
console.log(`
|
|
104
|
+
@prefix acl: <http://www.w3.org/ns/auth/acl#>.
|
|
105
|
+
|
|
106
|
+
<#nostrAuth>
|
|
107
|
+
a acl:Authorization;
|
|
108
|
+
acl:agent <did:nostr:${pk}>;
|
|
109
|
+
acl:accessTo <./>;
|
|
110
|
+
acl:mode acl:Read, acl:Write.
|
|
111
|
+
`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
main().catch(console.error);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "00f5d7c4-1da9-4e68-92c9-2b931f7c5750",
|
|
3
|
-
"email": "credtest@example.com",
|
|
4
|
-
"passwordHash": "$2b$10$oH0fl4a/riqSc4oXZ1pmLuSQOP9AlRSSrOMg7OlP5O2m.C39mOTL6",
|
|
5
|
-
"webId": "http://localhost:3101/credtest/#me",
|
|
6
|
-
"podName": "credtest",
|
|
7
|
-
"createdAt": "2025-12-27T14:04:29.630Z",
|
|
8
|
-
"lastLogin": "2025-12-27T14:04:29.865Z"
|
|
9
|
-
}
|