shogun-core 3.3.1 → 3.3.2
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/dist/ship/examples/ephemeral-cli.js +234 -0
- package/dist/ship/examples/identity-cli.js +503 -0
- package/dist/ship/examples/messenger-cli.js +745 -0
- package/dist/ship/examples/stealth-cli.js +433 -0
- package/dist/ship/examples/storage-cli.js +615 -0
- package/dist/ship/examples/vault-cli.js +444 -0
- package/dist/ship/examples/wallet-cli.js +767 -0
- package/dist/ship/implementation/SHIP_00.js +478 -0
- package/dist/ship/implementation/SHIP_01.js +433 -0
- package/dist/ship/implementation/SHIP_02.js +1366 -0
- package/dist/ship/implementation/SHIP_03.js +855 -0
- package/dist/ship/implementation/SHIP_04.js +589 -0
- package/dist/ship/implementation/SHIP_05.js +1064 -0
- package/dist/ship/implementation/SHIP_06.js +350 -0
- package/dist/ship/implementation/SHIP_07.js +635 -0
- package/dist/ship/index.js +17 -0
- package/dist/ship/interfaces/ISHIP_00.js +135 -0
- package/dist/ship/interfaces/ISHIP_01.js +128 -0
- package/dist/ship/interfaces/ISHIP_02.js +57 -0
- package/dist/ship/interfaces/ISHIP_03.js +61 -0
- package/dist/ship/interfaces/ISHIP_04.js +62 -0
- package/dist/ship/interfaces/ISHIP_05.js +59 -0
- package/dist/ship/interfaces/ISHIP_06.js +144 -0
- package/dist/ship/interfaces/ISHIP_07.js +194 -0
- package/dist/types/ship/examples/ephemeral-cli.d.ts +13 -0
- package/dist/types/ship/examples/identity-cli.d.ts +40 -0
- package/dist/types/ship/examples/messenger-cli.d.ts +37 -0
- package/dist/types/ship/examples/stealth-cli.d.ts +31 -0
- package/dist/types/ship/examples/storage-cli.d.ts +48 -0
- package/dist/types/ship/examples/vault-cli.d.ts +13 -0
- package/dist/types/ship/examples/wallet-cli.d.ts +131 -0
- package/dist/types/ship/implementation/SHIP_00.d.ts +113 -0
- package/dist/types/ship/implementation/SHIP_01.d.ts +80 -0
- package/dist/types/ship/implementation/SHIP_02.d.ts +297 -0
- package/dist/types/ship/implementation/SHIP_03.d.ts +127 -0
- package/dist/types/ship/implementation/SHIP_04.d.ts +76 -0
- package/dist/types/ship/implementation/SHIP_05.d.ts +70 -0
- package/dist/types/ship/implementation/SHIP_06.d.ts +66 -0
- package/dist/types/ship/implementation/SHIP_07.d.ts +101 -0
- package/dist/types/ship/index.d.ts +14 -0
- package/dist/types/ship/interfaces/ISHIP_00.d.ts +410 -0
- package/dist/types/ship/interfaces/ISHIP_01.d.ts +343 -0
- package/dist/types/ship/interfaces/ISHIP_02.d.ts +470 -0
- package/dist/types/ship/interfaces/ISHIP_03.d.ts +295 -0
- package/dist/types/ship/interfaces/ISHIP_04.d.ts +245 -0
- package/dist/types/ship/interfaces/ISHIP_05.d.ts +234 -0
- package/dist/types/ship/interfaces/ISHIP_06.d.ts +370 -0
- package/dist/types/ship/interfaces/ISHIP_07.d.ts +522 -0
- package/package.json +1 -1
- /package/dist/{config → src/config}/simplified-config.js +0 -0
- /package/dist/{core.js → src/core.js} +0 -0
- /package/dist/{examples → src/examples}/api-test.js +0 -0
- /package/dist/{examples → src/examples}/simple-api-test.js +0 -0
- /package/dist/{gundb → src/gundb}/api.js +0 -0
- /package/dist/{gundb → src/gundb}/crypto.js +0 -0
- /package/dist/{gundb → src/gundb}/db.js +0 -0
- /package/dist/{gundb → src/gundb}/derive.js +0 -0
- /package/dist/{gundb → src/gundb}/errors.js +0 -0
- /package/dist/{gundb → src/gundb}/index.js +0 -0
- /package/dist/{gundb → src/gundb}/rxjs.js +0 -0
- /package/dist/{gundb → src/gundb}/types.js +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{interfaces → src/interfaces}/common.js +0 -0
- /package/dist/{interfaces → src/interfaces}/events.js +0 -0
- /package/dist/{interfaces → src/interfaces}/plugin.js +0 -0
- /package/dist/{interfaces → src/interfaces}/shogun.js +0 -0
- /package/dist/{managers → src/managers}/AuthManager.js +0 -0
- /package/dist/{managers → src/managers}/CoreInitializer.js +0 -0
- /package/dist/{managers → src/managers}/EventManager.js +0 -0
- /package/dist/{managers → src/managers}/PluginManager.js +0 -0
- /package/dist/{migration-test.js → src/migration-test.js} +0 -0
- /package/dist/{plugins → src/plugins}/base.js +0 -0
- /package/dist/{plugins → src/plugins}/index.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/index.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/nostrConnector.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/nostrConnectorPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/nostrSigner.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/types.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/index.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/oauthConnector.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/oauthPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/types.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/index.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/types.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/web3Connector.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/web3ConnectorPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/web3Signer.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/index.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/types.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/webauthn.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/webauthnPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/webauthnSigner.js +0 -0
- /package/dist/{storage → src/storage}/storage.js +0 -0
- /package/dist/{types → src/types}/events.js +0 -0
- /package/dist/{types → src/types}/shogun.js +0 -0
- /package/dist/{utils → src/utils}/errorHandler.js +0 -0
- /package/dist/{utils → src/utils}/eventEmitter.js +0 -0
- /package/dist/{utils → src/utils}/validation.js +0 -0
- /package/dist/types/{config → src/config}/simplified-config.d.ts +0 -0
- /package/dist/types/{core.d.ts → src/core.d.ts} +0 -0
- /package/dist/types/{examples → src/examples}/api-test.d.ts +0 -0
- /package/dist/types/{examples → src/examples}/simple-api-test.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/api.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/crypto.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/db.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/derive.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/errors.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/index.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/rxjs.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/types.d.ts +0 -0
- /package/dist/types/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/types/{interfaces → src/interfaces}/common.d.ts +0 -0
- /package/dist/types/{interfaces → src/interfaces}/events.d.ts +0 -0
- /package/dist/types/{interfaces → src/interfaces}/plugin.d.ts +0 -0
- /package/dist/types/{interfaces → src/interfaces}/shogun.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/AuthManager.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/CoreInitializer.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/EventManager.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/PluginManager.d.ts +0 -0
- /package/dist/types/{migration-test.d.ts → src/migration-test.d.ts} +0 -0
- /package/dist/types/{plugins → src/plugins}/base.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/nostrConnector.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/nostrConnectorPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/nostrSigner.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/oauthConnector.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/oauthPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/web3Connector.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/web3ConnectorPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/web3Signer.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/webauthn.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/webauthnPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/webauthnSigner.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/storage.d.ts +0 -0
- /package/dist/types/{types → src/types}/events.d.ts +0 -0
- /package/dist/types/{types → src/types}/shogun.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/errorHandler.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/eventEmitter.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/validation.d.ts +0 -0
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SHIP-04: Multi-Modal Authentication Implementation
|
|
4
|
+
*
|
|
5
|
+
* Extends SHIP-00 to provide alternative authentication methods.
|
|
6
|
+
* Integrates existing Shogun Core plugins for OAuth, WebAuthn, Nostr, and Web3.
|
|
7
|
+
*
|
|
8
|
+
* Based on:
|
|
9
|
+
* - SHIP-00 for identity foundation
|
|
10
|
+
* - Shogun Core Plugins (OAuth, WebAuthn, Nostr, Web3)
|
|
11
|
+
* - External OAuth providers (Google, GitHub, etc.)
|
|
12
|
+
* - WebAuthn API for biometric auth
|
|
13
|
+
* - Nostr protocol for decentralized social
|
|
14
|
+
* - Web3 providers (MetaMask, WalletConnect)
|
|
15
|
+
*
|
|
16
|
+
* Features:
|
|
17
|
+
* ✅ OAuth authentication (Google, GitHub, Discord, etc.)
|
|
18
|
+
* ✅ WebAuthn/Passkeys (biometric, hardware keys)
|
|
19
|
+
* ✅ Nostr protocol integration
|
|
20
|
+
* ✅ Web3 wallet connection (MetaMask, etc.)
|
|
21
|
+
* ✅ SHIP-00 compatible (all methods return SEA keypair)
|
|
22
|
+
* ✅ Plugin-based architecture (modular)
|
|
23
|
+
*
|
|
24
|
+
* Inclusive Hierarchy:
|
|
25
|
+
* SHIP-04 → depends on → SHIP-00 ✅
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.SHIP_04 = void 0;
|
|
29
|
+
// Shogun Core plugins
|
|
30
|
+
const oauthPlugin_1 = require("../../src/plugins/oauth/oauthPlugin");
|
|
31
|
+
const webauthnPlugin_1 = require("../../src/plugins/webauthn/webauthnPlugin");
|
|
32
|
+
const nostrConnectorPlugin_1 = require("../../src/plugins/nostr/nostrConnectorPlugin");
|
|
33
|
+
const web3ConnectorPlugin_1 = require("../../src/plugins/web3/web3ConnectorPlugin");
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// IMPLEMENTATION
|
|
36
|
+
// ============================================================================
|
|
37
|
+
/**
|
|
38
|
+
* SHIP-04 Reference Implementation
|
|
39
|
+
*
|
|
40
|
+
* Provides multiple authentication methods on top of SHIP-00.
|
|
41
|
+
* All authentication methods are converted to SHIP-00 compatible format.
|
|
42
|
+
*/
|
|
43
|
+
class SHIP_04 {
|
|
44
|
+
constructor(identity, config = {}) {
|
|
45
|
+
this.initialized = false;
|
|
46
|
+
// Plugins
|
|
47
|
+
this.oauthPlugin = null;
|
|
48
|
+
this.webauthnPlugin = null;
|
|
49
|
+
this.nostrPlugin = null;
|
|
50
|
+
this.web3Plugin = null;
|
|
51
|
+
// Current auth method
|
|
52
|
+
this.currentAuthMethod = null;
|
|
53
|
+
this.identity = identity;
|
|
54
|
+
this.config = {
|
|
55
|
+
enableOAuth: config.enableOAuth ?? true,
|
|
56
|
+
enableWebAuthn: config.enableWebAuthn ?? true,
|
|
57
|
+
enableNostr: config.enableNostr ?? true,
|
|
58
|
+
enableWeb3: config.enableWeb3 ?? true,
|
|
59
|
+
oauthProviders: config.oauthProviders,
|
|
60
|
+
webAuthnRpName: config.webAuthnRpName ?? "Shogun",
|
|
61
|
+
webAuthnRpId: config.webAuthnRpId,
|
|
62
|
+
nostrRelays: config.nostrRelays ?? [
|
|
63
|
+
"wss://relay.damus.io",
|
|
64
|
+
"wss://relay.nostr.band",
|
|
65
|
+
],
|
|
66
|
+
web3Provider: config.web3Provider ?? "metamask",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// ========================================================================
|
|
70
|
+
// INITIALIZATION
|
|
71
|
+
// ========================================================================
|
|
72
|
+
async initialize() {
|
|
73
|
+
if (this.initialized) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
console.log("🔐 Initializing SHIP-04 (Multi-Modal Auth)...");
|
|
78
|
+
// Get ShogunCore instance from SHIP-00
|
|
79
|
+
const shogunCore = this.identity.getShogun();
|
|
80
|
+
if (!shogunCore) {
|
|
81
|
+
throw new Error("Cannot access ShogunCore from SHIP-00");
|
|
82
|
+
}
|
|
83
|
+
// Initialize enabled plugins
|
|
84
|
+
if (this.config.enableOAuth && this.config.oauthProviders) {
|
|
85
|
+
this.oauthPlugin = new oauthPlugin_1.OAuthPlugin({
|
|
86
|
+
providers: this.config.oauthProviders,
|
|
87
|
+
});
|
|
88
|
+
this.oauthPlugin.initialize(shogunCore);
|
|
89
|
+
console.log("✅ OAuth plugin initialized");
|
|
90
|
+
}
|
|
91
|
+
if (this.config.enableWebAuthn && typeof window !== "undefined") {
|
|
92
|
+
this.webauthnPlugin = new webauthnPlugin_1.WebauthnPlugin();
|
|
93
|
+
this.webauthnPlugin.initialize(shogunCore);
|
|
94
|
+
console.log("✅ WebAuthn plugin initialized");
|
|
95
|
+
}
|
|
96
|
+
if (this.config.enableNostr) {
|
|
97
|
+
this.nostrPlugin = new nostrConnectorPlugin_1.NostrConnectorPlugin();
|
|
98
|
+
this.nostrPlugin.initialize(shogunCore);
|
|
99
|
+
console.log("✅ Nostr plugin initialized");
|
|
100
|
+
}
|
|
101
|
+
if (this.config.enableWeb3) {
|
|
102
|
+
this.web3Plugin = new web3ConnectorPlugin_1.Web3ConnectorPlugin();
|
|
103
|
+
this.web3Plugin.initialize(shogunCore);
|
|
104
|
+
console.log("✅ Web3 plugin initialized");
|
|
105
|
+
}
|
|
106
|
+
this.initialized = true;
|
|
107
|
+
console.log("✅ SHIP-04 initialized with multi-modal authentication");
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throw new Error(`SHIP-04 initialization failed: ${error.message}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
isInitialized() {
|
|
114
|
+
return this.initialized;
|
|
115
|
+
}
|
|
116
|
+
getIdentity() {
|
|
117
|
+
return this.identity;
|
|
118
|
+
}
|
|
119
|
+
// ========================================================================
|
|
120
|
+
// OAUTH AUTHENTICATION
|
|
121
|
+
// ========================================================================
|
|
122
|
+
async loginWithOAuth(provider, redirectUri) {
|
|
123
|
+
this.ensureInitialized();
|
|
124
|
+
if (!this.oauthPlugin) {
|
|
125
|
+
return {
|
|
126
|
+
success: false,
|
|
127
|
+
error: "OAuth plugin not initialized",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
console.log(`🔐 Logging in with ${provider}...`);
|
|
132
|
+
// Use OAuth plugin's login method
|
|
133
|
+
// Note: This initiates OAuth flow and returns auth URL for redirect
|
|
134
|
+
const authResult = await this.oauthPlugin.login(provider);
|
|
135
|
+
if (!authResult.success) {
|
|
136
|
+
return {
|
|
137
|
+
success: false,
|
|
138
|
+
error: authResult.error || "OAuth login failed",
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
this.currentAuthMethod = "oauth";
|
|
142
|
+
await this.saveAuthMethod("oauth");
|
|
143
|
+
console.log(`✅ OAuth flow initiated for ${provider}`);
|
|
144
|
+
console.log(`💡 Complete authentication with handleOAuthCallback()`);
|
|
145
|
+
return {
|
|
146
|
+
success: true,
|
|
147
|
+
userPub: authResult.userPub,
|
|
148
|
+
username: authResult.username,
|
|
149
|
+
derivedAddress: authResult.derivedAddress,
|
|
150
|
+
provider: provider,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
console.error("❌ OAuth login error:", error);
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
error: error.message,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async handleOAuthCallback(code, provider) {
|
|
162
|
+
this.ensureInitialized();
|
|
163
|
+
if (!this.oauthPlugin) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
error: "OAuth plugin not initialized",
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
// Complete OAuth flow with code
|
|
171
|
+
const result = await this.oauthPlugin.completeOAuth(provider, code);
|
|
172
|
+
if (!result.success) {
|
|
173
|
+
return {
|
|
174
|
+
success: false,
|
|
175
|
+
error: result.error || "OAuth callback failed",
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
console.log(`✅ OAuth callback completed for ${provider}`);
|
|
179
|
+
return {
|
|
180
|
+
success: true,
|
|
181
|
+
provider,
|
|
182
|
+
email: result.userInfo?.email,
|
|
183
|
+
profilePicture: result.userInfo?.picture,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return {
|
|
188
|
+
success: false,
|
|
189
|
+
error: error.message,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
isOAuthAvailable(provider) {
|
|
194
|
+
if (!this.oauthPlugin)
|
|
195
|
+
return false;
|
|
196
|
+
const availableProviders = this.oauthPlugin.getAvailableProviders();
|
|
197
|
+
if (provider) {
|
|
198
|
+
return availableProviders.includes(provider);
|
|
199
|
+
}
|
|
200
|
+
return availableProviders.length > 0;
|
|
201
|
+
}
|
|
202
|
+
// ========================================================================
|
|
203
|
+
// WEBAUTHN AUTHENTICATION
|
|
204
|
+
// ========================================================================
|
|
205
|
+
async registerWithWebAuthn(username) {
|
|
206
|
+
this.ensureInitialized();
|
|
207
|
+
if (!this.webauthnPlugin) {
|
|
208
|
+
return {
|
|
209
|
+
success: false,
|
|
210
|
+
error: "WebAuthn plugin not initialized",
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
console.log(`🔐 Registering with WebAuthn: ${username}`);
|
|
215
|
+
// Register with WebAuthn plugin (handles derive internally)
|
|
216
|
+
const result = await this.webauthnPlugin.signUp(username);
|
|
217
|
+
if (!result.success) {
|
|
218
|
+
return {
|
|
219
|
+
success: false,
|
|
220
|
+
error: result.error || "WebAuthn registration failed",
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// Plugin already handled authentication with SHIP-00
|
|
224
|
+
// Just verify the user is logged in
|
|
225
|
+
const authResult = this.identity.getCurrentUser();
|
|
226
|
+
if (!authResult || !authResult.pub) {
|
|
227
|
+
return {
|
|
228
|
+
success: false,
|
|
229
|
+
error: "SHIP-00 authentication verification failed",
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
this.currentAuthMethod = "webauthn";
|
|
233
|
+
await this.saveAuthMethod("webauthn");
|
|
234
|
+
console.log("✅ Registered with WebAuthn");
|
|
235
|
+
return {
|
|
236
|
+
success: true,
|
|
237
|
+
userPub: result.userPub,
|
|
238
|
+
username: username,
|
|
239
|
+
derivedAddress: result.derivedAddress,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
console.error("❌ WebAuthn registration error:", error);
|
|
244
|
+
return {
|
|
245
|
+
success: false,
|
|
246
|
+
error: error.message,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async loginWithWebAuthn(username) {
|
|
251
|
+
this.ensureInitialized();
|
|
252
|
+
if (!this.webauthnPlugin) {
|
|
253
|
+
return {
|
|
254
|
+
success: false,
|
|
255
|
+
error: "WebAuthn plugin not initialized",
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
console.log(`🔐 Logging in with WebAuthn: ${username}`);
|
|
260
|
+
// Login with WebAuthn plugin (handles derive internally)
|
|
261
|
+
const result = await this.webauthnPlugin.login(username);
|
|
262
|
+
if (!result.success) {
|
|
263
|
+
return {
|
|
264
|
+
success: false,
|
|
265
|
+
error: result.error || "WebAuthn login failed",
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// Plugin already handled authentication with SHIP-00
|
|
269
|
+
// Just verify the user is logged in
|
|
270
|
+
const authResult = this.identity.getCurrentUser();
|
|
271
|
+
if (!authResult || !authResult.pub) {
|
|
272
|
+
return {
|
|
273
|
+
success: false,
|
|
274
|
+
error: "SHIP-00 authentication verification failed",
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
this.currentAuthMethod = "webauthn";
|
|
278
|
+
await this.saveAuthMethod("webauthn");
|
|
279
|
+
console.log("✅ Logged in with WebAuthn");
|
|
280
|
+
return {
|
|
281
|
+
success: true,
|
|
282
|
+
userPub: result.userPub,
|
|
283
|
+
username: username,
|
|
284
|
+
derivedAddress: result.derivedAddress,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
console.error("❌ WebAuthn login error:", error);
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
error: error.message,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
isWebAuthnAvailable() {
|
|
296
|
+
if (!this.webauthnPlugin)
|
|
297
|
+
return false;
|
|
298
|
+
return this.webauthnPlugin.isSupported();
|
|
299
|
+
}
|
|
300
|
+
// ========================================================================
|
|
301
|
+
// NOSTR AUTHENTICATION
|
|
302
|
+
// ========================================================================
|
|
303
|
+
async connectNostr() {
|
|
304
|
+
this.ensureInitialized();
|
|
305
|
+
if (!this.nostrPlugin) {
|
|
306
|
+
return {
|
|
307
|
+
success: false,
|
|
308
|
+
error: "Nostr plugin not initialized",
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
console.log("🔐 Connecting to Nostr...");
|
|
313
|
+
// Connect with Nostr plugin
|
|
314
|
+
const result = await this.nostrPlugin.connectNostrWallet();
|
|
315
|
+
if (!result.success || !result.credentials) {
|
|
316
|
+
return {
|
|
317
|
+
success: false,
|
|
318
|
+
error: result.error || "Nostr connection failed",
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
// Extract Nostr public key
|
|
322
|
+
const nostrPubkey = result.credentials.publicKey;
|
|
323
|
+
// Generate signature for SHIP-00 keypair derivation
|
|
324
|
+
// Nostr plugin generateCredentials needs (address, signature)
|
|
325
|
+
const message = `SHIP-04-NOSTR-${nostrPubkey}`;
|
|
326
|
+
// Request signature from Nostr extension
|
|
327
|
+
const shogun = this.identity.getShogun();
|
|
328
|
+
const gun = shogun?.db?.gun;
|
|
329
|
+
const crypto = shogun?.db?.crypto;
|
|
330
|
+
if (!gun || !crypto) {
|
|
331
|
+
return {
|
|
332
|
+
success: false,
|
|
333
|
+
error: "Cannot access Gun/crypto",
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
// For Nostr, we use the public key directly as the seed
|
|
337
|
+
const hashText = await crypto.hashText(nostrPubkey);
|
|
338
|
+
// Create deterministic SEA pair from Nostr pubkey
|
|
339
|
+
const seaPair = await gun.SEA.pair();
|
|
340
|
+
// Use plugin's login method which handles everything
|
|
341
|
+
// The plugin internally uses derive and calls core.login
|
|
342
|
+
const authResult = await this.nostrPlugin.login(nostrPubkey);
|
|
343
|
+
if (!authResult.success) {
|
|
344
|
+
return {
|
|
345
|
+
success: false,
|
|
346
|
+
error: authResult.error || "Nostr login failed",
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
// Plugin already handled authentication with SHIP-00
|
|
350
|
+
// Just verify the user is logged in
|
|
351
|
+
const ship00Result = this.identity.getCurrentUser();
|
|
352
|
+
if (!ship00Result || !ship00Result.pub) {
|
|
353
|
+
return {
|
|
354
|
+
success: false,
|
|
355
|
+
error: "SHIP-00 authentication verification failed",
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
this.currentAuthMethod = "nostr";
|
|
359
|
+
await this.saveAuthMethod("nostr");
|
|
360
|
+
console.log("✅ Connected with Nostr");
|
|
361
|
+
return {
|
|
362
|
+
success: true,
|
|
363
|
+
userPub: authResult.userPub,
|
|
364
|
+
username: authResult.username,
|
|
365
|
+
derivedAddress: authResult.derivedAddress,
|
|
366
|
+
nostrPubkey,
|
|
367
|
+
relays: this.config.nostrRelays,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
console.error("❌ Nostr connection error:", error);
|
|
372
|
+
return {
|
|
373
|
+
success: false,
|
|
374
|
+
error: error.message,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
async loginWithNostr() {
|
|
379
|
+
// Alias for connectNostr
|
|
380
|
+
return this.connectNostr();
|
|
381
|
+
}
|
|
382
|
+
isNostrAvailable() {
|
|
383
|
+
if (!this.nostrPlugin)
|
|
384
|
+
return false;
|
|
385
|
+
return this.nostrPlugin.isAvailable();
|
|
386
|
+
}
|
|
387
|
+
// ========================================================================
|
|
388
|
+
// WEB3 AUTHENTICATION
|
|
389
|
+
// ========================================================================
|
|
390
|
+
async connectWeb3() {
|
|
391
|
+
this.ensureInitialized();
|
|
392
|
+
if (!this.web3Plugin) {
|
|
393
|
+
return {
|
|
394
|
+
success: false,
|
|
395
|
+
error: "Web3 plugin not initialized",
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
console.log("🔐 Connecting to Web3 wallet...");
|
|
400
|
+
// Connect with Web3 plugin (MetaMask, etc.)
|
|
401
|
+
const result = await this.web3Plugin.connectMetaMask();
|
|
402
|
+
if (!result.success || !result.address) {
|
|
403
|
+
return {
|
|
404
|
+
success: false,
|
|
405
|
+
error: result.error || "Web3 connection failed",
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
// Use plugin's login method which handles derive and authentication internally
|
|
409
|
+
const authResult = await this.web3Plugin.login(result.address);
|
|
410
|
+
if (!authResult.success) {
|
|
411
|
+
return {
|
|
412
|
+
success: false,
|
|
413
|
+
error: authResult.error || "Web3 login failed",
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
// Plugin already handled authentication with SHIP-00
|
|
417
|
+
// Just verify the user is logged in
|
|
418
|
+
const ship00Result = this.identity.getCurrentUser();
|
|
419
|
+
if (!ship00Result || !ship00Result.pub) {
|
|
420
|
+
return {
|
|
421
|
+
success: false,
|
|
422
|
+
error: "SHIP-00 authentication verification failed",
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
this.currentAuthMethod = "web3";
|
|
426
|
+
await this.saveAuthMethod("web3");
|
|
427
|
+
console.log("✅ Connected with Web3 wallet");
|
|
428
|
+
return {
|
|
429
|
+
success: true,
|
|
430
|
+
userPub: authResult.userPub,
|
|
431
|
+
username: authResult.username || result.address,
|
|
432
|
+
derivedAddress: authResult.derivedAddress,
|
|
433
|
+
walletAddress: result.address,
|
|
434
|
+
chainId: result.chainId,
|
|
435
|
+
walletType: this.config.web3Provider,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
catch (error) {
|
|
439
|
+
console.error("❌ Web3 connection error:", error);
|
|
440
|
+
return {
|
|
441
|
+
success: false,
|
|
442
|
+
error: error.message,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
async loginWithWeb3(message) {
|
|
447
|
+
// Use custom message if provided
|
|
448
|
+
if (message) {
|
|
449
|
+
console.log(`💡 Using custom message: ${message}`);
|
|
450
|
+
}
|
|
451
|
+
return this.connectWeb3();
|
|
452
|
+
}
|
|
453
|
+
isWeb3Available() {
|
|
454
|
+
if (!this.web3Plugin)
|
|
455
|
+
return false;
|
|
456
|
+
return this.web3Plugin.isAvailable();
|
|
457
|
+
}
|
|
458
|
+
// ========================================================================
|
|
459
|
+
// UTILITIES
|
|
460
|
+
// ========================================================================
|
|
461
|
+
getAvailableAuthMethods() {
|
|
462
|
+
const methods = [];
|
|
463
|
+
// Password (always available via SHIP-00)
|
|
464
|
+
methods.push({
|
|
465
|
+
method: "password",
|
|
466
|
+
available: true,
|
|
467
|
+
configured: true,
|
|
468
|
+
lastUsed: this.currentAuthMethod === "password" ? Date.now() : undefined,
|
|
469
|
+
});
|
|
470
|
+
// OAuth
|
|
471
|
+
if (this.config.enableOAuth) {
|
|
472
|
+
methods.push({
|
|
473
|
+
method: "oauth",
|
|
474
|
+
available: this.oauthPlugin !== null,
|
|
475
|
+
configured: this.config.oauthProviders !== undefined,
|
|
476
|
+
lastUsed: this.currentAuthMethod === "oauth" ? Date.now() : undefined,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
// WebAuthn
|
|
480
|
+
if (this.config.enableWebAuthn) {
|
|
481
|
+
methods.push({
|
|
482
|
+
method: "webauthn",
|
|
483
|
+
available: this.isWebAuthnAvailable(),
|
|
484
|
+
configured: true,
|
|
485
|
+
lastUsed: this.currentAuthMethod === "webauthn" ? Date.now() : undefined,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
// Nostr
|
|
489
|
+
if (this.config.enableNostr) {
|
|
490
|
+
methods.push({
|
|
491
|
+
method: "nostr",
|
|
492
|
+
available: this.isNostrAvailable(),
|
|
493
|
+
configured: true,
|
|
494
|
+
lastUsed: this.currentAuthMethod === "nostr" ? Date.now() : undefined,
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
// Web3
|
|
498
|
+
if (this.config.enableWeb3) {
|
|
499
|
+
methods.push({
|
|
500
|
+
method: "web3",
|
|
501
|
+
available: this.isWeb3Available(),
|
|
502
|
+
configured: true,
|
|
503
|
+
lastUsed: this.currentAuthMethod === "web3" ? Date.now() : undefined,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
return methods;
|
|
507
|
+
}
|
|
508
|
+
getCurrentAuthMethod() {
|
|
509
|
+
return this.currentAuthMethod;
|
|
510
|
+
}
|
|
511
|
+
async clearAuth() {
|
|
512
|
+
this.currentAuthMethod = null;
|
|
513
|
+
// Clear from Gun storage
|
|
514
|
+
try {
|
|
515
|
+
const shogun = this.identity.getShogun();
|
|
516
|
+
const gun = shogun?.db?.gun;
|
|
517
|
+
if (gun) {
|
|
518
|
+
const user = gun.user();
|
|
519
|
+
if (user && user.is) {
|
|
520
|
+
await user.get(SHIP_04.NODES.AUTH_METHOD).put(null);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
catch (error) {
|
|
525
|
+
console.error("Error clearing auth method from Gun:", error);
|
|
526
|
+
}
|
|
527
|
+
console.log("✅ Authentication method cleared");
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Save current auth method to Gun (optional persistence)
|
|
531
|
+
*/
|
|
532
|
+
async saveAuthMethod(method) {
|
|
533
|
+
try {
|
|
534
|
+
const shogun = this.identity.getShogun();
|
|
535
|
+
const gun = shogun?.db?.gun;
|
|
536
|
+
if (!gun)
|
|
537
|
+
return;
|
|
538
|
+
const user = gun.user();
|
|
539
|
+
if (!user || !user.is)
|
|
540
|
+
return;
|
|
541
|
+
await user.get(SHIP_04.NODES.AUTH_METHOD).put(method);
|
|
542
|
+
console.log(`✅ Auth method saved to Gun: ${method}`);
|
|
543
|
+
}
|
|
544
|
+
catch (error) {
|
|
545
|
+
console.error("Error saving auth method to Gun:", error);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Load last used auth method from Gun
|
|
550
|
+
*/
|
|
551
|
+
async loadAuthMethod() {
|
|
552
|
+
try {
|
|
553
|
+
const shogun = this.identity.getShogun();
|
|
554
|
+
const gun = shogun?.db?.gun;
|
|
555
|
+
if (!gun)
|
|
556
|
+
return null;
|
|
557
|
+
const user = gun.user();
|
|
558
|
+
if (!user || !user.is)
|
|
559
|
+
return null;
|
|
560
|
+
return new Promise((resolve) => {
|
|
561
|
+
const timeout = setTimeout(() => resolve(null), 3000);
|
|
562
|
+
user.get(SHIP_04.NODES.AUTH_METHOD).once((data) => {
|
|
563
|
+
clearTimeout(timeout);
|
|
564
|
+
resolve(data || null);
|
|
565
|
+
});
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
catch (error) {
|
|
569
|
+
console.error("Error loading auth method from Gun:", error);
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
// ========================================================================
|
|
574
|
+
// PRIVATE HELPERS
|
|
575
|
+
// ========================================================================
|
|
576
|
+
ensureInitialized() {
|
|
577
|
+
if (!this.initialized) {
|
|
578
|
+
throw new Error("SHIP-04 not initialized. Call initialize() first.");
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
exports.SHIP_04 = SHIP_04;
|
|
583
|
+
// GunDB Node Names for SHIP-04 storage
|
|
584
|
+
// Note: SHIP-04 is a coordinator that delegates to plugins.
|
|
585
|
+
// Plugins manage their own storage internally (OAuth, WebAuthn, Nostr, Web3).
|
|
586
|
+
// We only track the current authentication method used.
|
|
587
|
+
SHIP_04.NODES = {
|
|
588
|
+
AUTH_METHOD: "current_auth_method", // Last used auth method (in user space)
|
|
589
|
+
};
|