@principal-ai/control-tower-core 0.1.20 → 0.1.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/dist/abstractions/AuthAdapter.d.ts +1 -3
- package/dist/abstractions/AuthAdapter.d.ts.map +1 -1
- package/dist/adapters/mock/MockAuthAdapter.d.ts +12 -6
- package/dist/adapters/mock/MockAuthAdapter.d.ts.map +1 -1
- package/dist/adapters/mock/MockAuthAdapter.js +20 -114
- package/dist/adapters/websocket/WebSocketServerTransportAdapter.d.ts.map +1 -1
- package/dist/adapters/websocket/WebSocketServerTransportAdapter.js +65 -62
- package/dist/client/BaseClient.d.ts +28 -3
- package/dist/client/BaseClient.d.ts.map +1 -1
- package/dist/client/BaseClient.js +72 -26
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +6 -6
- package/dist/index.mjs +125 -185
- package/dist/index.mjs.map +6 -6
- package/dist/server/BaseServer.js +1 -1
- package/dist/types/auth.d.ts +16 -20
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { TokenPayload
|
|
1
|
+
import type { TokenPayload } from '../types/index.js';
|
|
2
2
|
export interface IAuthAdapter {
|
|
3
|
-
authenticate(credentials: Credentials): Promise<AuthResult>;
|
|
4
3
|
validateToken(token: string): Promise<TokenPayload>;
|
|
5
4
|
generateToken?(payload: TokenPayload): Promise<string>;
|
|
6
5
|
refreshToken?(token: string): Promise<string>;
|
|
@@ -8,6 +7,5 @@ export interface IAuthAdapter {
|
|
|
8
7
|
getCurrentToken?(): string | null;
|
|
9
8
|
isAuthRequired?(): boolean;
|
|
10
9
|
getAuthTimeout?(): number;
|
|
11
|
-
getSupportedCredentialTypes?(): CredentialType[];
|
|
12
10
|
}
|
|
13
11
|
//# sourceMappingURL=AuthAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthAdapter.d.ts","sourceRoot":"","sources":["../../src/abstractions/AuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,
|
|
1
|
+
{"version":3,"file":"AuthAdapter.d.ts","sourceRoot":"","sources":["../../src/abstractions/AuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,YAAY;IAE3B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAGpD,aAAa,CAAC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,YAAY,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,WAAW,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3C,eAAe,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC;IAGlC,cAAc,CAAC,IAAI,OAAO,CAAC;IAC3B,cAAc,CAAC,IAAI,MAAM,CAAC;CAC3B"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { IAuthAdapter } from '../../abstractions/AuthAdapter.js';
|
|
2
|
-
import type { TokenPayload
|
|
2
|
+
import type { TokenPayload } from '../../types/index.js';
|
|
3
3
|
export declare class MockAuthAdapter implements IAuthAdapter {
|
|
4
4
|
private tokens;
|
|
5
5
|
private revokedTokens;
|
|
6
|
-
private users;
|
|
7
6
|
private simulateLatency;
|
|
8
7
|
private shouldFailAuth;
|
|
9
8
|
private tokenCounter;
|
|
9
|
+
private currentToken;
|
|
10
10
|
constructor(options?: {
|
|
11
11
|
simulateLatency?: number;
|
|
12
12
|
shouldFailAuth?: boolean;
|
|
@@ -15,16 +15,22 @@ export declare class MockAuthAdapter implements IAuthAdapter {
|
|
|
15
15
|
generateToken(payload: TokenPayload): Promise<string>;
|
|
16
16
|
refreshToken(token: string): Promise<string>;
|
|
17
17
|
revokeToken(token: string): Promise<void>;
|
|
18
|
-
|
|
18
|
+
getCurrentToken(): string | null;
|
|
19
19
|
isAuthRequired(): boolean;
|
|
20
20
|
getAuthTimeout(): number;
|
|
21
|
-
getSupportedCredentialTypes(): CredentialType[];
|
|
22
21
|
private simulateDelay;
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Create and store a test token for a user
|
|
24
|
+
*/
|
|
25
|
+
createTestToken(userId: string, options?: {
|
|
26
|
+
permissions?: string[];
|
|
27
|
+
metadata?: Record<string, unknown>;
|
|
28
|
+
expiresIn?: number;
|
|
29
|
+
}): Promise<string>;
|
|
25
30
|
getTokenCount(): number;
|
|
26
31
|
getRevokedTokenCount(): number;
|
|
27
32
|
clearTokens(): void;
|
|
28
33
|
setFailAuth(fail: boolean): void;
|
|
34
|
+
setCurrentToken(token: string | null): void;
|
|
29
35
|
}
|
|
30
36
|
//# sourceMappingURL=MockAuthAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MockAuthAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/mock/MockAuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"MockAuthAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/mock/MockAuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,YAAY,CAAuB;gBAE/B,OAAO,CAAC,EAAE;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B;IAKK,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBnD,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBrD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB5C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/C,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,cAAc,IAAI,OAAO;IAIzB,cAAc,IAAI,MAAM;YAKV,aAAa;IAM3B;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAC9C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,MAAM,CAAC;IAYnB,aAAa,IAAI,MAAM;IAIvB,oBAAoB,IAAI,MAAM;IAI9B,WAAW,IAAI,IAAI;IAMnB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIhC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;CAG5C"}
|
|
@@ -5,25 +5,12 @@ class MockAuthAdapter {
|
|
|
5
5
|
constructor(options) {
|
|
6
6
|
this.tokens = new Map();
|
|
7
7
|
this.revokedTokens = new Set();
|
|
8
|
-
this.users = new Map();
|
|
9
8
|
this.simulateLatency = 0;
|
|
10
9
|
this.shouldFailAuth = false;
|
|
11
10
|
this.tokenCounter = 0;
|
|
11
|
+
this.currentToken = null;
|
|
12
12
|
this.simulateLatency = options?.simulateLatency ?? 0;
|
|
13
13
|
this.shouldFailAuth = options?.shouldFailAuth ?? false;
|
|
14
|
-
// Add some default test users
|
|
15
|
-
this.addUser('testuser', 'password123', {
|
|
16
|
-
userId: 'user-1',
|
|
17
|
-
email: 'test@example.com',
|
|
18
|
-
username: 'testuser',
|
|
19
|
-
permissions: ['read', 'write']
|
|
20
|
-
});
|
|
21
|
-
this.addUser('admin', 'admin123', {
|
|
22
|
-
userId: 'user-admin',
|
|
23
|
-
email: 'admin@example.com',
|
|
24
|
-
username: 'admin',
|
|
25
|
-
permissions: ['read', 'write', 'admin']
|
|
26
|
-
});
|
|
27
14
|
}
|
|
28
15
|
async validateToken(token) {
|
|
29
16
|
await this.simulateDelay();
|
|
@@ -78,119 +65,34 @@ class MockAuthAdapter {
|
|
|
78
65
|
this.tokens.delete(token);
|
|
79
66
|
this.revokedTokens.add(token);
|
|
80
67
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (this.shouldFailAuth) {
|
|
84
|
-
return {
|
|
85
|
-
success: false,
|
|
86
|
-
error: 'Mock authentication failed'
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
switch (credentials.type) {
|
|
90
|
-
case 'password': {
|
|
91
|
-
if (!credentials.username || !credentials.password) {
|
|
92
|
-
return {
|
|
93
|
-
success: false,
|
|
94
|
-
error: 'Username and password required'
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
const user = this.users.get(credentials.username);
|
|
98
|
-
if (!user || user.password !== credentials.password) {
|
|
99
|
-
return {
|
|
100
|
-
success: false,
|
|
101
|
-
error: 'Invalid credentials'
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
const token = await this.generateToken(user.payload);
|
|
105
|
-
const refreshToken = `refresh-${token}`;
|
|
106
|
-
this.tokens.set(refreshToken, user.payload);
|
|
107
|
-
return {
|
|
108
|
-
success: true,
|
|
109
|
-
token,
|
|
110
|
-
refreshToken,
|
|
111
|
-
user: user.payload,
|
|
112
|
-
userId: user.payload.userId,
|
|
113
|
-
expiresIn: 3600
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
case 'token':
|
|
117
|
-
case 'jwt':
|
|
118
|
-
case 'bearer': {
|
|
119
|
-
if (!credentials.token) {
|
|
120
|
-
return {
|
|
121
|
-
success: false,
|
|
122
|
-
error: 'Token required'
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
const payload = await this.validateToken(credentials.token);
|
|
127
|
-
return {
|
|
128
|
-
success: true,
|
|
129
|
-
token: credentials.token,
|
|
130
|
-
user: payload,
|
|
131
|
-
userId: payload.userId,
|
|
132
|
-
expiresIn: 3600
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
return {
|
|
137
|
-
success: false,
|
|
138
|
-
error: error.message
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
case 'oauth': {
|
|
143
|
-
// Simulate OAuth flow
|
|
144
|
-
if (!credentials.code) {
|
|
145
|
-
return {
|
|
146
|
-
success: false,
|
|
147
|
-
error: 'OAuth code required'
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
// Create a mock OAuth user
|
|
151
|
-
const payload = {
|
|
152
|
-
userId: `oauth-user-${Date.now()}`,
|
|
153
|
-
email: 'oauth@example.com',
|
|
154
|
-
username: 'oauthuser',
|
|
155
|
-
permissions: ['read', 'write']
|
|
156
|
-
};
|
|
157
|
-
const token = await this.generateToken(payload);
|
|
158
|
-
return {
|
|
159
|
-
success: true,
|
|
160
|
-
token,
|
|
161
|
-
user: payload,
|
|
162
|
-
userId: payload.userId,
|
|
163
|
-
expiresIn: 3600
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
default:
|
|
167
|
-
return {
|
|
168
|
-
success: false,
|
|
169
|
-
error: 'Unsupported credential type'
|
|
170
|
-
};
|
|
171
|
-
}
|
|
68
|
+
getCurrentToken() {
|
|
69
|
+
return this.currentToken;
|
|
172
70
|
}
|
|
173
|
-
// New methods for enhanced auth interface
|
|
174
71
|
isAuthRequired() {
|
|
175
72
|
return false; // Mock adapter doesn't require auth by default
|
|
176
73
|
}
|
|
177
74
|
getAuthTimeout() {
|
|
178
75
|
return 10000; // 10 seconds for testing
|
|
179
76
|
}
|
|
180
|
-
getSupportedCredentialTypes() {
|
|
181
|
-
return ['password', 'token', 'jwt', 'bearer', 'oauth'];
|
|
182
|
-
}
|
|
183
77
|
// Test helper methods
|
|
184
78
|
async simulateDelay() {
|
|
185
79
|
if (this.simulateLatency > 0) {
|
|
186
80
|
await new Promise(resolve => setTimeout(resolve, this.simulateLatency));
|
|
187
81
|
}
|
|
188
82
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Create and store a test token for a user
|
|
85
|
+
*/
|
|
86
|
+
async createTestToken(userId, options) {
|
|
87
|
+
const payload = {
|
|
88
|
+
userId,
|
|
89
|
+
permissions: options?.permissions ?? ['read', 'write'],
|
|
90
|
+
metadata: options?.metadata,
|
|
91
|
+
expiresAt: options?.expiresIn ? Date.now() + options.expiresIn : undefined
|
|
92
|
+
};
|
|
93
|
+
const token = await this.generateToken(payload);
|
|
94
|
+
this.currentToken = token;
|
|
95
|
+
return token;
|
|
194
96
|
}
|
|
195
97
|
getTokenCount() {
|
|
196
98
|
return this.tokens.size;
|
|
@@ -201,9 +103,13 @@ class MockAuthAdapter {
|
|
|
201
103
|
clearTokens() {
|
|
202
104
|
this.tokens.clear();
|
|
203
105
|
this.revokedTokens.clear();
|
|
106
|
+
this.currentToken = null;
|
|
204
107
|
}
|
|
205
108
|
setFailAuth(fail) {
|
|
206
109
|
this.shouldFailAuth = fail;
|
|
207
110
|
}
|
|
111
|
+
setCurrentToken(token) {
|
|
112
|
+
this.currentToken = token;
|
|
113
|
+
}
|
|
208
114
|
}
|
|
209
115
|
exports.MockAuthAdapter = MockAuthAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketServerTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/WebSocketServerTransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,
|
|
1
|
+
{"version":3,"file":"WebSocketServerTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/WebSocketServerTransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEhD,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,+BAAgC,YAAW,iBAAiB;IACvE,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,aAAa,CAAgC;IAGrD,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,SAAS,CAAC,CAAS;IAG3B,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAS;IAG/B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,IAAI,CAA8C;IAG1D,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,MAAM,CAAiC;gBAEnC,MAAM,CAAC,EAAE,8BAA8B;IAUnD,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAclC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCjE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,EAAE,IAAI,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC7E,uBAAuB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YA2BpD,gBAAgB;YA8EhB,mBAAmB;YAuCnB,iBAAiB;IAiF/B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,YAAY;IAMd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA4C3C,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,QAAQ,IAAI,eAAe;IAI3B,WAAW,IAAI,OAAO;IAKtB,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC,uBAAuB,IAAI,gBAAgB,EAAE;IAI7C,cAAc,IAAI,MAAM;IAIxB,OAAO,IAAI,YAAY,GAAG,aAAa;IAIvC,cAAc,IAAI,OAAO;IAIzB,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -115,21 +115,22 @@ class WebSocketServerTransportAdapter {
|
|
|
115
115
|
}
|
|
116
116
|
async handleConnection(ws, req) {
|
|
117
117
|
const clientId = this.generateId();
|
|
118
|
-
// Step 1: Try
|
|
118
|
+
// Step 1: Try token authentication via Authorization header
|
|
119
119
|
let authenticated = false;
|
|
120
|
-
let
|
|
120
|
+
let userId;
|
|
121
|
+
let metadata;
|
|
121
122
|
if (this.authAdapter && req.headers.authorization) {
|
|
122
123
|
const token = this.extractBearerToken(req.headers.authorization);
|
|
123
124
|
if (token) {
|
|
124
125
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
authenticated = authResult.success;
|
|
126
|
+
const tokenPayload = await this.authAdapter.validateToken(token);
|
|
127
|
+
authenticated = true;
|
|
128
|
+
userId = tokenPayload.userId;
|
|
129
|
+
metadata = tokenPayload.metadata;
|
|
130
130
|
}
|
|
131
131
|
catch {
|
|
132
|
-
// Header auth failed but don't reject connection
|
|
132
|
+
// Header auth failed but don't reject connection yet
|
|
133
|
+
// Client can still authenticate via message
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
}
|
|
@@ -138,8 +139,8 @@ class WebSocketServerTransportAdapter {
|
|
|
138
139
|
id: clientId,
|
|
139
140
|
ws,
|
|
140
141
|
authenticated,
|
|
141
|
-
userId
|
|
142
|
-
metadata
|
|
142
|
+
userId,
|
|
143
|
+
metadata,
|
|
143
144
|
connectedAt: Date.now()
|
|
144
145
|
};
|
|
145
146
|
this.clients.set(clientId, client);
|
|
@@ -219,70 +220,72 @@ class WebSocketServerTransportAdapter {
|
|
|
219
220
|
if (!this.authAdapter) {
|
|
220
221
|
this.sendToClient(client, {
|
|
221
222
|
id: this.generateId(),
|
|
222
|
-
type: '
|
|
223
|
-
payload: { error: 'No auth adapter configured' },
|
|
223
|
+
type: 'auth_result',
|
|
224
|
+
payload: { success: false, error: 'No auth adapter configured' },
|
|
225
|
+
timestamp: Date.now()
|
|
226
|
+
});
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const payload = message.payload;
|
|
230
|
+
// Token-based authentication only
|
|
231
|
+
if (!payload.token || typeof payload.token !== 'string') {
|
|
232
|
+
this.sendToClient(client, {
|
|
233
|
+
id: this.generateId(),
|
|
234
|
+
type: 'auth_result',
|
|
235
|
+
payload: { success: false, error: 'Token required for authentication' },
|
|
224
236
|
timestamp: Date.now()
|
|
225
237
|
});
|
|
226
238
|
return;
|
|
227
239
|
}
|
|
228
240
|
try {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
clearTimeout(client.authTimeout);
|
|
235
|
-
client.authTimeout = undefined;
|
|
236
|
-
}
|
|
237
|
-
// Update client state
|
|
238
|
-
client.authenticated = true;
|
|
239
|
-
client.userId = result.userId || result.user?.userId;
|
|
240
|
-
client.metadata = result.metadata || result.user?.metadata;
|
|
241
|
-
// Send success response
|
|
242
|
-
this.sendToClient(client, {
|
|
243
|
-
id: this.generateId(),
|
|
244
|
-
type: 'auth_success',
|
|
245
|
-
payload: {
|
|
246
|
-
userId: client.userId,
|
|
247
|
-
metadata: client.metadata
|
|
248
|
-
},
|
|
249
|
-
timestamp: Date.now()
|
|
250
|
-
});
|
|
251
|
-
// Notify handlers about authentication
|
|
252
|
-
const authMessage = {
|
|
253
|
-
id: this.generateId(),
|
|
254
|
-
type: 'client_authenticated',
|
|
255
|
-
payload: {
|
|
256
|
-
clientId: client.id,
|
|
257
|
-
userId: client.userId,
|
|
258
|
-
metadata: client.metadata
|
|
259
|
-
},
|
|
260
|
-
timestamp: Date.now()
|
|
261
|
-
};
|
|
262
|
-
this.messageHandlers.forEach(handler => handler(authMessage));
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
// Send error response
|
|
266
|
-
this.sendToClient(client, {
|
|
267
|
-
id: this.generateId(),
|
|
268
|
-
type: 'auth_error',
|
|
269
|
-
payload: { error: result.error || 'Authentication failed' },
|
|
270
|
-
timestamp: Date.now()
|
|
271
|
-
});
|
|
272
|
-
// Optionally close connection
|
|
273
|
-
if (this.config.closeOnAuthFailure) {
|
|
274
|
-
client.ws.close(1008, 'Authentication failed');
|
|
275
|
-
this.clients.delete(client.id);
|
|
276
|
-
}
|
|
241
|
+
const tokenPayload = await this.authAdapter.validateToken(payload.token);
|
|
242
|
+
// Clear auth timeout
|
|
243
|
+
if (client.authTimeout) {
|
|
244
|
+
clearTimeout(client.authTimeout);
|
|
245
|
+
client.authTimeout = undefined;
|
|
277
246
|
}
|
|
247
|
+
// Update client state
|
|
248
|
+
client.authenticated = true;
|
|
249
|
+
client.userId = tokenPayload.userId;
|
|
250
|
+
client.metadata = tokenPayload.metadata;
|
|
251
|
+
// Send success response
|
|
252
|
+
this.sendToClient(client, {
|
|
253
|
+
id: this.generateId(),
|
|
254
|
+
type: 'auth_result',
|
|
255
|
+
payload: {
|
|
256
|
+
success: true,
|
|
257
|
+
userId: client.userId
|
|
258
|
+
},
|
|
259
|
+
timestamp: Date.now()
|
|
260
|
+
});
|
|
261
|
+
// Notify handlers about authentication
|
|
262
|
+
const authMessage = {
|
|
263
|
+
id: this.generateId(),
|
|
264
|
+
type: 'client_authenticated',
|
|
265
|
+
payload: {
|
|
266
|
+
clientId: client.id,
|
|
267
|
+
userId: client.userId,
|
|
268
|
+
metadata: client.metadata
|
|
269
|
+
},
|
|
270
|
+
timestamp: Date.now()
|
|
271
|
+
};
|
|
272
|
+
this.messageHandlers.forEach(handler => handler(authMessage));
|
|
278
273
|
}
|
|
279
274
|
catch (error) {
|
|
280
275
|
this.sendToClient(client, {
|
|
281
276
|
id: this.generateId(),
|
|
282
|
-
type: '
|
|
283
|
-
payload: {
|
|
277
|
+
type: 'auth_result',
|
|
278
|
+
payload: {
|
|
279
|
+
success: false,
|
|
280
|
+
error: error.message
|
|
281
|
+
},
|
|
284
282
|
timestamp: Date.now()
|
|
285
283
|
});
|
|
284
|
+
// Optionally close connection on auth failure
|
|
285
|
+
if (this.config.closeOnAuthFailure) {
|
|
286
|
+
client.ws.close(1008, 'Authentication failed');
|
|
287
|
+
this.clients.delete(client.id);
|
|
288
|
+
}
|
|
286
289
|
}
|
|
287
290
|
}
|
|
288
291
|
extractBearerToken(authHeader) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectionState, Event, RoomState, RoomUser, LockRequest, Lock,
|
|
1
|
+
import type { ConnectionState, Event, RoomState, RoomUser, LockRequest, Lock, AuthenticatePayload } from '../types/index.js';
|
|
2
2
|
import type { ITransportAdapter } from '../abstractions/TransportAdapter.js';
|
|
3
3
|
import type { IAuthAdapter } from '../abstractions/AuthAdapter.js';
|
|
4
4
|
import type { IStorageAdapter } from '../abstractions/StorageAdapter.js';
|
|
@@ -19,6 +19,12 @@ export interface ClientEvents {
|
|
|
19
19
|
connected: {
|
|
20
20
|
url: string;
|
|
21
21
|
};
|
|
22
|
+
authenticated: {
|
|
23
|
+
userId: string;
|
|
24
|
+
};
|
|
25
|
+
authentication_failed: {
|
|
26
|
+
error: string;
|
|
27
|
+
};
|
|
22
28
|
disconnected: {
|
|
23
29
|
code: number;
|
|
24
30
|
reason: string;
|
|
@@ -71,11 +77,29 @@ export declare class BaseClient extends TypedEventEmitter<ClientEvents> {
|
|
|
71
77
|
private reconnectAttempts;
|
|
72
78
|
private reconnectTimer;
|
|
73
79
|
private lastConnectionUrl;
|
|
74
|
-
private
|
|
80
|
+
private lastToken;
|
|
75
81
|
constructor(config: ClientConfig);
|
|
76
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Connect to the server with an optional authentication token.
|
|
84
|
+
*
|
|
85
|
+
* @param url The WebSocket URL to connect to
|
|
86
|
+
* @param token Optional JWT token for authentication
|
|
87
|
+
*/
|
|
88
|
+
connect(url: string, token?: string): Promise<void>;
|
|
77
89
|
disconnect(): Promise<void>;
|
|
78
90
|
reconnect(): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Send an authenticate message to the server with the current token.
|
|
93
|
+
* This must be called after connect() to complete the authentication handshake.
|
|
94
|
+
*
|
|
95
|
+
* @param options Optional authentication options including deviceId and metadata
|
|
96
|
+
* @throws Error if client is not connected or no auth token is available
|
|
97
|
+
*/
|
|
98
|
+
authenticate(options?: Omit<AuthenticatePayload, 'token'>): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Check if the client has an auth token available.
|
|
101
|
+
*/
|
|
102
|
+
hasAuthToken(): boolean;
|
|
79
103
|
joinRoom(roomId: string): Promise<void>;
|
|
80
104
|
leaveRoom(): Promise<void>;
|
|
81
105
|
broadcast(event: Event): Promise<void>;
|
|
@@ -89,6 +113,7 @@ export declare class BaseClient extends TypedEventEmitter<ClientEvents> {
|
|
|
89
113
|
private handleMessage;
|
|
90
114
|
private handleError;
|
|
91
115
|
private handleClose;
|
|
116
|
+
private handleAuthResult;
|
|
92
117
|
private handleRoomJoined;
|
|
93
118
|
private handleRoomLeft;
|
|
94
119
|
private handleEventBroadcast;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../../src/client/BaseClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAGf,KAAK,EACL,SAAS,EACT,QAAQ,EACR,WAAW,EACX,IAAI,EACJ,
|
|
1
|
+
{"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../../src/client/BaseClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
15
15
|
this.reconnectAttempts = 0;
|
|
16
16
|
this.reconnectTimer = null;
|
|
17
17
|
this.lastConnectionUrl = null;
|
|
18
|
-
this.
|
|
18
|
+
this.lastToken = null;
|
|
19
19
|
this.config = config;
|
|
20
20
|
this.transport = config.transport;
|
|
21
21
|
this.auth = config.auth;
|
|
@@ -26,43 +26,41 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
26
26
|
this.transport.onClose(this.handleClose.bind(this));
|
|
27
27
|
}
|
|
28
28
|
// Connection Management
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Connect to the server with an optional authentication token.
|
|
31
|
+
*
|
|
32
|
+
* @param url The WebSocket URL to connect to
|
|
33
|
+
* @param token Optional JWT token for authentication
|
|
34
|
+
*/
|
|
35
|
+
async connect(url, token) {
|
|
30
36
|
if (this.connectionState !== 'disconnected') {
|
|
31
37
|
throw new Error('Client is already connected or connecting');
|
|
32
38
|
}
|
|
33
39
|
this.connectionState = 'connecting';
|
|
34
40
|
this.lastConnectionUrl = url;
|
|
35
|
-
this.
|
|
41
|
+
this.lastToken = token || null;
|
|
36
42
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
if (authResult.success && authResult.token) {
|
|
42
|
-
this.authToken = authResult.token;
|
|
43
|
-
this.userId = authResult.user?.userId || authResult.userId || '';
|
|
44
|
-
tokenToApply = authResult.token;
|
|
45
|
-
}
|
|
43
|
+
// Use provided token or try to get existing token from auth adapter
|
|
44
|
+
let tokenToApply = token || null;
|
|
45
|
+
if (!tokenToApply && this.auth && typeof this.auth.getCurrentToken === 'function') {
|
|
46
|
+
tokenToApply = this.auth.getCurrentToken();
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
this.authToken = currentToken;
|
|
52
|
-
tokenToApply = currentToken;
|
|
53
|
-
// Try to validate and get user info from token
|
|
48
|
+
if (tokenToApply) {
|
|
49
|
+
this.authToken = tokenToApply;
|
|
50
|
+
// Try to validate and get user info from token
|
|
51
|
+
if (this.auth) {
|
|
54
52
|
try {
|
|
55
|
-
const payload = await this.auth.validateToken(
|
|
53
|
+
const payload = await this.auth.validateToken(tokenToApply);
|
|
56
54
|
this.userId = payload.userId;
|
|
57
55
|
}
|
|
58
56
|
catch {
|
|
59
|
-
// Token validation failed,
|
|
57
|
+
// Token validation failed locally, server will validate
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
// Apply token to transport if it supports it
|
|
61
|
+
if (typeof this.transport.setAuthToken === 'function') {
|
|
62
|
+
this.transport.setAuthToken(tokenToApply);
|
|
63
|
+
}
|
|
66
64
|
}
|
|
67
65
|
const options = {
|
|
68
66
|
url,
|
|
@@ -113,7 +111,41 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
113
111
|
if (this.connectionState !== 'disconnected') {
|
|
114
112
|
await this.disconnect();
|
|
115
113
|
}
|
|
116
|
-
await this.connect(this.lastConnectionUrl, this.
|
|
114
|
+
await this.connect(this.lastConnectionUrl, this.lastToken || undefined);
|
|
115
|
+
}
|
|
116
|
+
// Authentication
|
|
117
|
+
/**
|
|
118
|
+
* Send an authenticate message to the server with the current token.
|
|
119
|
+
* This must be called after connect() to complete the authentication handshake.
|
|
120
|
+
*
|
|
121
|
+
* @param options Optional authentication options including deviceId and metadata
|
|
122
|
+
* @throws Error if client is not connected or no auth token is available
|
|
123
|
+
*/
|
|
124
|
+
async authenticate(options) {
|
|
125
|
+
if (this.connectionState !== 'connected') {
|
|
126
|
+
throw new Error('Client must be connected to authenticate');
|
|
127
|
+
}
|
|
128
|
+
if (!this.authToken) {
|
|
129
|
+
throw new Error('No auth token available. Connect with credentials first.');
|
|
130
|
+
}
|
|
131
|
+
const payload = {
|
|
132
|
+
token: this.authToken,
|
|
133
|
+
...options
|
|
134
|
+
};
|
|
135
|
+
const message = {
|
|
136
|
+
id: this.generateId(),
|
|
137
|
+
type: 'authenticate',
|
|
138
|
+
payload,
|
|
139
|
+
timestamp: Date.now()
|
|
140
|
+
};
|
|
141
|
+
await this.transport.send(message);
|
|
142
|
+
// Response will be handled in handleMessage via auth_result
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Check if the client has an auth token available.
|
|
146
|
+
*/
|
|
147
|
+
hasAuthToken() {
|
|
148
|
+
return this.authToken !== null;
|
|
117
149
|
}
|
|
118
150
|
// Room Management
|
|
119
151
|
async joinRoom(roomId) {
|
|
@@ -205,6 +237,9 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
205
237
|
async handleMessage(message) {
|
|
206
238
|
try {
|
|
207
239
|
switch (message.type) {
|
|
240
|
+
case 'auth_result':
|
|
241
|
+
await this.handleAuthResult(message.payload);
|
|
242
|
+
break;
|
|
208
243
|
case 'room_joined':
|
|
209
244
|
await this.handleRoomJoined(message.payload);
|
|
210
245
|
break;
|
|
@@ -250,6 +285,17 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
250
285
|
}
|
|
251
286
|
}
|
|
252
287
|
}
|
|
288
|
+
async handleAuthResult(payload) {
|
|
289
|
+
if (payload.success) {
|
|
290
|
+
if (payload.userId) {
|
|
291
|
+
this.userId = payload.userId;
|
|
292
|
+
}
|
|
293
|
+
await this.emit('authenticated', { userId: this.userId || '' });
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
await this.emit('authentication_failed', { error: payload.error || 'Authentication failed' });
|
|
297
|
+
}
|
|
298
|
+
}
|
|
253
299
|
async handleRoomJoined(payload) {
|
|
254
300
|
this.currentRoomId = payload.roomId;
|
|
255
301
|
// Deserialize the plain objects back to Maps
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { EventType, BaseEvent, FileAction, FileChangeEvent, GitStatusEvent, CommitEvent, BranchChangeEvent, CursorPositionEvent, Event, TokenPayload, AuthResult,
|
|
1
|
+
export { EventType, BaseEvent, FileAction, FileChangeEvent, GitStatusEvent, CommitEvent, BranchChangeEvent, CursorPositionEvent, Event, TokenPayload, AuthResult, JWTConfig, AuthenticatePayload, AuthenticateResult, RoomPermission, Room, RoomUser, UserStatus, RoomState, RoomConfig, LockType, LockPriority, Lock, LockRequest, LockQueueItem, LockState, ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler, ExperimentalFeatureConfig, ClientPredicate, BroadcastResult, BroadcastOptions, ExperimentalUsageEvent, ExperimentalFeatureError, PresenceStatus, DeviceInfo, UserPresence, PresenceConfig, PresenceChangeEvent, ActivityUpdate } from './types/index.js';
|
|
2
2
|
export { ITransportAdapter, IStorageAdapter, StorageOperation, IAuthAdapter, TypedEventEmitter, EventListener, UnsubscribeFn, RoomManager, LockManager, DefaultRoomManager, DefaultLockManager, PresenceManager, DefaultPresenceManager, PresenceExtension, ExtendedUserPresence } from './abstractions/index.js';
|
|
3
3
|
export { MockTransportAdapter, MockStorageAdapter, MockAuthAdapter } from './adapters/mock/index.js';
|
|
4
4
|
export { WebSocketServerTransportAdapter, type WebSocketServerTransportConfig, WebSocketClientTransportAdapter, type WebSocketClientConfig } from './adapters/websocket/index.js';
|