@iobroker/socket-classes 2.3.7 → 2.4.3
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/README.md +11 -1
- package/build/index.d.ts +2 -2
- package/build/index.js.map +1 -1
- package/build/lib/passportSocket.d.ts +4 -3
- package/build/lib/passportSocket.js +174 -115
- package/build/lib/passportSocket.js.map +1 -1
- package/build/lib/socketCommands.js +10 -6
- package/build/lib/socketCommands.js.map +1 -1
- package/build/lib/socketCommandsAdmin.js +49 -35
- package/build/lib/socketCommandsAdmin.js.map +1 -1
- package/build/lib/socketCommon.js +32 -4
- package/build/lib/socketCommon.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1032,7 +1032,17 @@ Unsubscribe from file changes in ioBroker DB
|
|
|
1032
1032
|
Placeholder for the next version (at the beginning of the line):
|
|
1033
1033
|
### **WORK IN PROGRESS**
|
|
1034
1034
|
-->
|
|
1035
|
-
### 2.3
|
|
1035
|
+
### 2.4.3 (2026-08-31)
|
|
1036
|
+
* (@GermanBluefox) Log messages are only sent to the sockets that subscribed to them. `sendLog()` emitted `log` to every connected socket, so as soon as one client called `requireLog(true)`, all other clients received the log too - including clients of other browsers and clients whose user does not have the rights to subscribe to the log at all.
|
|
1037
|
+
* (@GermanBluefox) `logout` destroys the express session again. It used `socket.id` as the session id, which only worked as long as `@iobroker/ws-server` filled the socket id with the session id from the `connect.sid` cookie. The socket id is a per-connection transport identifier generated on the server now, so the session to destroy is taken from `socket._sessionID` / `socket.conn.request.sessionID` instead.
|
|
1038
|
+
* (@joltcoke) Decode the websocket auth query so encoded credentials work
|
|
1039
|
+
|
|
1040
|
+
### 2.4.0 (2026-08-27)
|
|
1041
|
+
* (@joltcoke) Security: an upgrade request that carries neither credentials nor a cookie header no longer crashes the adapter. `sessionID` is assigned only inside the cookie branch of `authorize()`, so such a request reached the session store lookup with it still undefined and js-controller threw while validating the id. The exception escaped the synchronous `verifyClient()` callback of the websocket server, so any unauthenticated client could stop an instance running with `auth: true`. The request is now rejected through `auth.fail()`, and `PassportHttpRequest.sessionID` is declared optional so the compiler rejects a future unguarded use. Affects 2.2.21 up to and including 2.3.8. Reported and fixed by Florian Schirmer.
|
|
1042
|
+
* (@GermanBluefox) Security: `authorize()` answers every upgrade request exactly once now and turns an unexpected exception into a regular rejection instead of letting it escape into the upgrade handler, so a future error on that path cannot take the adapter down again.
|
|
1043
|
+
|
|
1044
|
+
### 2.3.8 (2026-08-24)
|
|
1045
|
+
* (@GermanBluefox) Security: `decrypt` and `encrypt` only serve a request from the process-wide cached system secret if the caller is an administrator. The cache is shared across all sockets, so once any user who may read `system.config` had populated it, every authenticated user could encrypt and decrypt with the system secret regardless of their own rights. For non-administrators the secret is now resolved through a read that is ACL-checked for the calling user.
|
|
1036
1046
|
* (@GermanBluefox) Security: `clientSubscribe` and `clientUnsubscribe` now require the `other.sendto` permission. They deliver a message to an arbitrary adapter instance via `sendTo`, but were not covered by any permission check, so an authenticated user without `other.sendto` could reach any instance. Reported by Santosh Kumar Puppala.
|
|
1037
1047
|
* (@GermanBluefox) Security: `eventsThreshold` now requires the `other.execute` permission. Enabling the threshold unsubscribes the adapter from all state patterns for every connected client, so it must not be reachable by a low-privilege user.
|
|
1038
1048
|
|
package/build/index.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ export { SocketCommandsAdmin } from './lib/socketCommandsAdmin';
|
|
|
5
5
|
export { SocketCommands, type SupportedFeature, COMMANDS_PERMISSIONS } from './lib/socketCommands';
|
|
6
6
|
export { SocketCommon, type Server, type SocketSettings, type SocketIoOptions, type WhiteListSettings, } from './lib/socketCommon';
|
|
7
7
|
export { SocketAdmin } from './lib/socketAdmin';
|
|
8
|
-
import { authorize as passportSocket, type PassportHttpRequest, type Store } from './lib/passportSocket';
|
|
9
|
-
export { passport, cookieParser, passportSocket, type PassportHttpRequest, type Store };
|
|
8
|
+
import { authorize as passportSocket, type AuthOptions, type PassportHttpRequest, type Store } from './lib/passportSocket';
|
|
9
|
+
export { passport, cookieParser, passportSocket, type AuthOptions, type PassportHttpRequest, type Store };
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;AAoBvB,mBApBF,kBAAQ,CAoBE;AAnBjB,kEAAyC;AAmBtB,uBAnBZ,uBAAY,CAmBY;AAhB/B,iEAAgE;AAAvD,0HAAA,mBAAmB,OAAA;AAC5B,uDAAmG;AAA1F,gHAAA,cAAc,OAAA;AAAyB,sHAAA,oBAAoB,OAAA;AACpE,mDAM4B;AALxB,4GAAA,YAAY,OAAA;AAMhB,iDAAgD;AAAvC,0GAAA,WAAW,OAAA;AACpB,yDAK8B;AACG,+FALhB,0BAAc,OAKgB"}
|
|
@@ -8,7 +8,7 @@ export interface PassportHttpRequest extends IncomingMessage {
|
|
|
8
8
|
};
|
|
9
9
|
query: Record<string, string>;
|
|
10
10
|
cookie: Record<string, string> | undefined;
|
|
11
|
-
sessionID
|
|
11
|
+
sessionID?: string;
|
|
12
12
|
user: {
|
|
13
13
|
logged_in: boolean;
|
|
14
14
|
user?: string;
|
|
@@ -46,7 +46,7 @@ export interface Store {
|
|
|
46
46
|
};
|
|
47
47
|
}) => void;
|
|
48
48
|
}
|
|
49
|
-
export
|
|
49
|
+
export interface AuthOptions {
|
|
50
50
|
passport: passport.PassportStatic;
|
|
51
51
|
cookieParser: (secret: string | string[] | undefined, options?: {
|
|
52
52
|
decode?(val: string): string;
|
|
@@ -61,4 +61,5 @@ export declare function authorize(auth: {
|
|
|
61
61
|
store?: Store;
|
|
62
62
|
userProperty?: string;
|
|
63
63
|
noBasicAuth?: boolean;
|
|
64
|
-
}
|
|
64
|
+
}
|
|
65
|
+
export declare function authorize(auth: AuthOptions): (req: IncomingMessage, accept: (err: boolean) => void) => void;
|
|
@@ -20,81 +20,66 @@ function parseCookie(auth, cookieHeader) {
|
|
|
20
20
|
});
|
|
21
21
|
return result;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Decode a query string component the way a URL query is meant to be read: '+' becomes a
|
|
25
|
+
* space and percent escapes are resolved. A malformed percent sequence is kept verbatim
|
|
26
|
+
* instead of throwing, so a broken query can never crash the upgrade handler.
|
|
27
|
+
*/
|
|
28
|
+
function decodeQueryComponent(value) {
|
|
29
|
+
try {
|
|
30
|
+
return decodeURIComponent(value.replace(/\+/g, ' '));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
23
36
|
function getQuery(url) {
|
|
24
37
|
const query = (url || '').split('?')[1] || '';
|
|
25
|
-
const parts = query.split('&');
|
|
26
38
|
const result = {};
|
|
27
|
-
for (
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
for (const part of query.split('&')) {
|
|
40
|
+
if (!part) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Split on the first '=' only and decode both sides. Splitting on every '=' would
|
|
44
|
+
// drop everything after a '=' inside the value (e.g. base64 padding), and without
|
|
45
|
+
// decoding an url-encoded credential would be compared in its encoded form and
|
|
46
|
+
// rejected, so a user or password containing & = # % + or whitespace could not be
|
|
47
|
+
// authenticated at all.
|
|
48
|
+
const eq = part.indexOf('=');
|
|
49
|
+
const rawKey = eq === -1 ? part : part.slice(0, eq);
|
|
50
|
+
const rawValue = eq === -1 ? '' : part.slice(eq + 1);
|
|
51
|
+
result[decodeQueryComponent(rawKey)] = decodeQueryComponent(rawValue);
|
|
30
52
|
}
|
|
31
53
|
return result;
|
|
32
54
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (auth.checkUser && extendedReq.query.user && extendedReq.query.pass) {
|
|
45
|
-
return auth.checkUser(extendedReq.query.user, extendedReq.query.pass, (error, result) => {
|
|
46
|
-
if (error) {
|
|
47
|
-
return auth.fail(extendedReq, 'Cannot check user', false, accept);
|
|
48
|
-
}
|
|
49
|
-
if (!result) {
|
|
50
|
-
return auth.fail(extendedReq, 'User not found', false, accept);
|
|
51
|
-
}
|
|
52
|
-
extendedReq.user = result;
|
|
53
|
-
extendedReq.user.user = extendedReq.query.user;
|
|
54
|
-
extendedReq.user.logged_in = true;
|
|
55
|
-
auth.success(extendedReq, accept);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
extendedReq.cookie = parseCookie(auth, extendedReq.headers.cookie || '');
|
|
59
|
-
if (extendedReq.cookie && extendedReq.headers.cookie) {
|
|
60
|
-
extendedReq.sessionID = extendedReq.cookie['connect.sid'] || '';
|
|
61
|
-
const accessToken = extendedReq.headers.cookie.split(';').find(c => c.trim().startsWith('access_token='));
|
|
62
|
-
// Authentication with access token in cookies
|
|
63
|
-
if (accessToken) {
|
|
64
|
-
void auth.store?.get(`a:${accessToken.split('=')[1]}`, (err, token) => {
|
|
65
|
-
const tokenData = token;
|
|
66
|
-
if (err) {
|
|
67
|
-
return auth.fail(extendedReq, `Error in session store:\n${err.message}`, true, accept);
|
|
68
|
-
}
|
|
69
|
-
if (!tokenData?.user) {
|
|
70
|
-
return auth.fail(extendedReq, 'No session found', false, accept);
|
|
71
|
-
}
|
|
72
|
-
// extendedReq.user
|
|
73
|
-
extendedReq.user = { logged_in: true, user: tokenData.user };
|
|
74
|
-
auth.success(extendedReq, accept);
|
|
75
|
-
});
|
|
76
|
-
return;
|
|
55
|
+
/**
|
|
56
|
+
* Try every supported authentication of an upgrade request and answer it through `auth.success` or `auth.fail`.
|
|
57
|
+
* Never call this directly, use `authorize()`, which catches what this throws.
|
|
58
|
+
*/
|
|
59
|
+
function authenticate(auth, extendedReq, accept) {
|
|
60
|
+
extendedReq.query = getQuery(extendedReq.url);
|
|
61
|
+
// Authentication with user, password in a query
|
|
62
|
+
if (auth.checkUser && extendedReq.query.user && extendedReq.query.pass) {
|
|
63
|
+
return auth.checkUser(extendedReq.query.user, extendedReq.query.pass, (error, result) => {
|
|
64
|
+
if (error) {
|
|
65
|
+
return auth.fail(extendedReq, 'Cannot check user', false, accept);
|
|
77
66
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
// Authentication with access token as Bearer token
|
|
96
|
-
if (extendedReq.headers.authentication?.startsWith('Bearer ')) {
|
|
97
|
-
void auth.store?.get(`a:${extendedReq.headers.authentication.substring(7)}`, (err, token) => {
|
|
67
|
+
if (!result) {
|
|
68
|
+
return auth.fail(extendedReq, 'User not found', false, accept);
|
|
69
|
+
}
|
|
70
|
+
extendedReq.user = result;
|
|
71
|
+
extendedReq.user.user = extendedReq.query.user;
|
|
72
|
+
extendedReq.user.logged_in = true;
|
|
73
|
+
auth.success(extendedReq, accept);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
extendedReq.cookie = parseCookie(auth, extendedReq.headers.cookie || '');
|
|
77
|
+
if (extendedReq.cookie && extendedReq.headers.cookie) {
|
|
78
|
+
extendedReq.sessionID = extendedReq.cookie['connect.sid'] || '';
|
|
79
|
+
const accessToken = extendedReq.headers.cookie.split(';').find(c => c.trim().startsWith('access_token='));
|
|
80
|
+
// Authentication with access token in cookies
|
|
81
|
+
if (accessToken) {
|
|
82
|
+
void auth.store?.get(`a:${accessToken.split('=')[1]}`, (err, token) => {
|
|
98
83
|
const tokenData = token;
|
|
99
84
|
if (err) {
|
|
100
85
|
return auth.fail(extendedReq, `Error in session store:\n${err.message}`, true, accept);
|
|
@@ -108,63 +93,137 @@ function authorize(auth) {
|
|
|
108
93
|
});
|
|
109
94
|
return;
|
|
110
95
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
.split(':');
|
|
117
|
-
const username = parts.shift();
|
|
118
|
-
const password = parts.join(':');
|
|
119
|
-
if (auth.checkUser && password && username) {
|
|
120
|
-
return auth.checkUser(username, password, (error, result) => {
|
|
121
|
-
if (error) {
|
|
122
|
-
return auth.fail(extendedReq, 'Cannot check user', false, accept);
|
|
123
|
-
}
|
|
124
|
-
if (!result) {
|
|
125
|
-
return auth.fail(extendedReq, 'User not found', false, accept);
|
|
126
|
-
}
|
|
127
|
-
extendedReq.user = result;
|
|
128
|
-
extendedReq.user.user = username;
|
|
129
|
-
extendedReq.user.logged_in = true;
|
|
130
|
-
auth.success(extendedReq, accept);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
extendedReq.user = {
|
|
135
|
-
logged_in: false,
|
|
136
|
-
};
|
|
137
|
-
auth.store?.get(extendedReq.sessionID, (err, session) => {
|
|
138
|
-
// session looks like:
|
|
139
|
-
// {
|
|
140
|
-
// cookie: {
|
|
141
|
-
// originalMaxAge: 5999991,
|
|
142
|
-
// expires: '2025-02-07T17:15:06.466Z',
|
|
143
|
-
// httpOnly: true,
|
|
144
|
-
// path: '/',
|
|
145
|
-
// },
|
|
146
|
-
// passport: {
|
|
147
|
-
// user: 'admin',
|
|
148
|
-
// },
|
|
149
|
-
// };
|
|
96
|
+
}
|
|
97
|
+
// Authentication with access token in a query
|
|
98
|
+
if (extendedReq.query.token) {
|
|
99
|
+
void auth.store?.get(`a:${extendedReq.query.token}`, (err, token) => {
|
|
100
|
+
const tokenData = token;
|
|
150
101
|
if (err) {
|
|
151
102
|
return auth.fail(extendedReq, `Error in session store:\n${err.message}`, true, accept);
|
|
152
103
|
}
|
|
153
|
-
if (!
|
|
104
|
+
if (!tokenData?.user) {
|
|
154
105
|
return auth.fail(extendedReq, 'No session found', false, accept);
|
|
155
106
|
}
|
|
156
|
-
|
|
157
|
-
|
|
107
|
+
// extendedReq.user
|
|
108
|
+
extendedReq.user = { logged_in: true, user: tokenData.user };
|
|
109
|
+
auth.success(extendedReq, accept);
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Authentication with access token as Bearer token
|
|
114
|
+
if (extendedReq.headers.authentication?.startsWith('Bearer ')) {
|
|
115
|
+
void auth.store?.get(`a:${extendedReq.headers.authentication.substring(7)}`, (err, token) => {
|
|
116
|
+
const tokenData = token;
|
|
117
|
+
if (err) {
|
|
118
|
+
return auth.fail(extendedReq, `Error in session store:\n${err.message}`, true, accept);
|
|
158
119
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return auth.fail(extendedReq, 'User not authorized through passport. (User Property not found)', false, accept);
|
|
120
|
+
if (!tokenData?.user) {
|
|
121
|
+
return auth.fail(extendedReq, 'No session found', false, accept);
|
|
162
122
|
}
|
|
163
123
|
// extendedReq.user
|
|
164
|
-
extendedReq.user =
|
|
165
|
-
extendedReq.user.logged_in = true;
|
|
124
|
+
extendedReq.user = { logged_in: true, user: tokenData.user };
|
|
166
125
|
auth.success(extendedReq, accept);
|
|
167
126
|
});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Basic authentication
|
|
130
|
+
if (auth.checkUser && !auth.noBasicAuth && extendedReq.headers.authentication?.startsWith('Basic ')) {
|
|
131
|
+
// extract username and password
|
|
132
|
+
const parts = Buffer.from(extendedReq.headers.authentication.substring(6), 'base64')
|
|
133
|
+
.toString('utf-8')
|
|
134
|
+
.split(':');
|
|
135
|
+
const username = parts.shift();
|
|
136
|
+
const password = parts.join(':');
|
|
137
|
+
if (auth.checkUser && password && username) {
|
|
138
|
+
return auth.checkUser(username, password, (error, result) => {
|
|
139
|
+
if (error) {
|
|
140
|
+
return auth.fail(extendedReq, 'Cannot check user', false, accept);
|
|
141
|
+
}
|
|
142
|
+
if (!result) {
|
|
143
|
+
return auth.fail(extendedReq, 'User not found', false, accept);
|
|
144
|
+
}
|
|
145
|
+
extendedReq.user = result;
|
|
146
|
+
extendedReq.user.user = username;
|
|
147
|
+
extendedReq.user.logged_in = true;
|
|
148
|
+
auth.success(extendedReq, accept);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
extendedReq.user = {
|
|
153
|
+
logged_in: false,
|
|
154
|
+
};
|
|
155
|
+
// sessionID is only assigned inside the cookie branch above, so a request
|
|
156
|
+
// without a cookie header reaches this point with it still undefined. The
|
|
157
|
+
// session store rejects that with a thrown error instead of a callback,
|
|
158
|
+
// which takes down the upgrade handler of the whole adapter.
|
|
159
|
+
if (!extendedReq.sessionID) {
|
|
160
|
+
return auth.fail(extendedReq, 'No session id', false, accept);
|
|
161
|
+
}
|
|
162
|
+
auth.store?.get(extendedReq.sessionID, (err, session) => {
|
|
163
|
+
// session looks like:
|
|
164
|
+
// {
|
|
165
|
+
// cookie: {
|
|
166
|
+
// originalMaxAge: 5999991,
|
|
167
|
+
// expires: '2025-02-07T17:15:06.466Z',
|
|
168
|
+
// httpOnly: true,
|
|
169
|
+
// path: '/',
|
|
170
|
+
// },
|
|
171
|
+
// passport: {
|
|
172
|
+
// user: 'admin',
|
|
173
|
+
// },
|
|
174
|
+
// };
|
|
175
|
+
if (err) {
|
|
176
|
+
return auth.fail(extendedReq, `Error in session store:\n${err.message}`, true, accept);
|
|
177
|
+
}
|
|
178
|
+
if (!session) {
|
|
179
|
+
return auth.fail(extendedReq, 'No session found', false, accept);
|
|
180
|
+
}
|
|
181
|
+
if (!session.passport) {
|
|
182
|
+
return auth.fail(extendedReq, 'Passport was not initialized', true, accept);
|
|
183
|
+
}
|
|
184
|
+
const userKey = session.passport.user;
|
|
185
|
+
if (!userKey) {
|
|
186
|
+
return auth.fail(extendedReq, 'User not authorized through passport. (User Property not found)', false, accept);
|
|
187
|
+
}
|
|
188
|
+
// extendedReq.user
|
|
189
|
+
extendedReq.user = session.passport;
|
|
190
|
+
extendedReq.user.logged_in = true;
|
|
191
|
+
auth.success(extendedReq, accept);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function authorize(auth) {
|
|
195
|
+
if (!auth.passport) {
|
|
196
|
+
throw new Error("passport is required to use require('passport'), please install passport");
|
|
197
|
+
}
|
|
198
|
+
if (!auth.cookieParser) {
|
|
199
|
+
throw new Error("cookieParser is required use require('cookie-parser'), connect.cookieParser or express.cookieParser");
|
|
200
|
+
}
|
|
201
|
+
return function (req, accept) {
|
|
202
|
+
const extendedReq = req;
|
|
203
|
+
// The websocket server calls this from its synchronous `verifyClient` hook and does not catch
|
|
204
|
+
// anything, so a throw in here does not just fail one connection, it takes the adapter down.
|
|
205
|
+
// Answer every request exactly once and turn an unexpected error into a normal rejection.
|
|
206
|
+
let answered = false;
|
|
207
|
+
const answerOnce = (err) => {
|
|
208
|
+
if (answered) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
answered = true;
|
|
212
|
+
accept(err);
|
|
213
|
+
};
|
|
214
|
+
try {
|
|
215
|
+
authenticate(auth, extendedReq, answerOnce);
|
|
216
|
+
}
|
|
217
|
+
catch (e) {
|
|
218
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
219
|
+
try {
|
|
220
|
+
auth.fail(extendedReq, `Error in authorization:\n${message}`, true, answerOnce);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// even the failure handler gave up, just reject the connection
|
|
224
|
+
answerOnce(false);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
168
227
|
};
|
|
169
228
|
}
|
|
170
229
|
//# sourceMappingURL=passportSocket.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passportSocket.js","sourceRoot":"","sources":["../../src/lib/passportSocket.ts"],"names":[],"mappings":";AAAA,yGAAyG;AACzG,0EAA0E;;
|
|
1
|
+
{"version":3,"file":"passportSocket.js","sourceRoot":"","sources":["../../src/lib/passportSocket.ts"],"names":[],"mappings":";AAAA,yGAAyG;AACzG,0EAA0E;;AAqV1E,8BAsCC;AApTD,SAAS,WAAW,CAChB,IAMC,EACD,YAAoB;IAEpB,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpD,kBAAkB;IAClB,MAAM,GAAG,GAAgB;QACrB,OAAO,EAAE;YACL,MAAM,EAAE,YAAY;SACvB;KACJ,CAAC;IAEF,IAAI,MAA0C,CAAC;IAE/C,KAAK,YAAY,CAAC,GAAsB,EAAE,EAAsB,EAAE,CAAC,GAAW,EAAQ,EAAE;QACpF,IAAI,GAAG,EAAE,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,OAAO,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,KAAa;IACvC,IAAI,CAAC;QACD,OAAO,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,GAAuB;IACrC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,SAAS;QACb,CAAC;QACD,kFAAkF;QAClF,kFAAkF;QAClF,+EAA+E;QAC/E,kFAAkF;QAClF,wBAAwB;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,MAAM,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAqBD;;;GAGG;AACH,SAAS,YAAY,CAAC,IAAiB,EAAE,WAAgC,EAAE,MAA8B;IACrG,WAAW,CAAC,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE9C,gDAAgD;IAChD,IAAI,IAAI,CAAC,SAAS,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACrE,OAAO,IAAI,CAAC,SAAS,CACjB,WAAW,CAAC,KAAK,CAAC,IAAI,EACtB,WAAW,CAAC,KAAK,CAAC,IAAI,EACtB,CAAC,KAAmB,EAAE,MAA8C,EAAE,EAAE;YACpE,IAAI,KAAK,EAAE,CAAC;gBACR,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACV,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACnE,CAAC;YAED,WAAW,CAAC,IAAI,GAAG,MAAM,CAAC;YAC1B,WAAW,CAAC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;YAC/C,WAAW,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC,CACJ,CAAC;IACN,CAAC;IAED,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACzE,IAAI,WAAW,CAAC,MAAM,IAAI,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACnD,WAAW,CAAC,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QAEhE,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;QAE1G,8CAA8C;QAC9C,IAAI,WAAW,EAAE,CAAC;YACd,KAAK,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAU,EAAE,KAAU,EAAQ,EAAE;gBACpF,MAAM,SAAS,GAAG,KAA6B,CAAC;gBAEhD,IAAI,GAAG,EAAE,CAAC;oBACN,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,4BAA4B,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC3F,CAAC;gBACD,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;oBACnB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;gBACrE,CAAC;gBACD,mBAAmB;gBACnB,WAAW,CAAC,IAAI,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC7D,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;YACH,OAAO;QACX,CAAC;IACL,CAAC;IAED,8CAA8C;IAC9C,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,GAAU,EAAE,KAAU,EAAQ,EAAE;YAClF,MAAM,SAAS,GAAG,KAA6B,CAAC;YAEhD,IAAI,GAAG,EAAE,CAAC;gBACN,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,4BAA4B,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3F,CAAC;YACD,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;gBACnB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACrE,CAAC;YACD,mBAAmB;YACnB,WAAW,CAAC,IAAI,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;YAC7D,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QACH,OAAO;IACX,CAAC;IAED,mDAAmD;IACnD,IAAI,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5D,KAAK,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAU,EAAE,KAAU,EAAQ,EAAE;YAC1G,MAAM,SAAS,GAAG,KAA6B,CAAC;YAEhD,IAAI,GAAG,EAAE,CAAC;gBACN,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,4BAA4B,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3F,CAAC;YACD,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;gBACnB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACrE,CAAC;YACD,mBAAmB;YACnB,WAAW,CAAC,IAAI,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;YAC7D,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QACH,OAAO;IACX,CAAC;IAED,uBAAuB;IACvB,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClG,gCAAgC;QAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;aAC/E,QAAQ,CAAC,OAAO,CAAC;aACjB,KAAK,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,SAAS,CACjB,QAAQ,EACR,QAAQ,EACR,CAAC,KAAmB,EAAE,MAA8C,EAAE,EAAE;gBACpE,IAAI,KAAK,EAAE,CAAC;oBACR,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;gBACtE,CAAC;gBACD,IAAI,CAAC,MAAM,EAAE,CAAC;oBACV,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;gBACnE,CAAC;gBAED,WAAW,CAAC,IAAI,GAAG,MAAM,CAAC;gBAC1B,WAAW,CAAC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;gBACjC,WAAW,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBAClC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YACtC,CAAC,CACJ,CAAC;QACN,CAAC;IACL,CAAC;IAED,WAAW,CAAC,IAAI,GAAG;QACf,SAAS,EAAE,KAAK;KACnB,CAAC;IAEF,0EAA0E;IAC1E,0EAA0E;IAC1E,wEAAwE;IACxE,6DAA6D;IAC7D,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,GAAG,CACX,WAAW,CAAC,SAAS,EACrB,CACI,GAAU,EACV,OAUC,EACG,EAAE;QACN,sBAAsB;QACtB,IAAI;QACJ,gBAAgB;QAChB,mCAAmC;QACnC,+CAA+C;QAC/C,0BAA0B;QAC1B,qBAAqB;QACrB,SAAS;QACT,kBAAkB;QAClB,yBAAyB;QACzB,SAAS;QACT,KAAK;QAEL,IAAI,GAAG,EAAE,CAAC;YACN,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,4BAA4B,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3F,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,8BAA8B,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAEtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,IAAI,CAAC,IAAI,CACZ,WAAW,EACX,iEAAiE,EACjE,KAAK,EACL,MAAM,CACT,CAAC;QACN,CAAC;QAED,mBAAmB;QACnB,WAAW,CAAC,IAAI,GAAG,OAAO,CAAC,QAAiD,CAAC;QAC7E,WAAW,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC,CACJ,CAAC;AACN,CAAC;AAED,SAAgB,SAAS,CAAC,IAAiB;IACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAChG,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACX,qGAAqG,CACxG,CAAC;IACN,CAAC;IAED,OAAO,UAAU,GAAoB,EAAE,MAA8B;QACjE,MAAM,WAAW,GAAG,GAA0B,CAAC;QAE/C,8FAA8F;QAC9F,6FAA6F;QAC7F,0FAA0F;QAC1F,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,UAAU,GAAG,CAAC,GAAY,EAAQ,EAAE;YACtC,IAAI,QAAQ,EAAE,CAAC;gBACX,OAAO;YACX,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC,CAAC;QAEF,IAAI,CAAC;YACD,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,4BAA4B,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;YACpF,CAAC;YAAC,MAAM,CAAC;gBACL,+DAA+D;gBAC/D,UAAU,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACL,CAAC;IACL,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -1000,6 +1000,10 @@ class SocketCommands {
|
|
|
1000
1000
|
* @param callback callback `(error?: Error) => void`
|
|
1001
1001
|
*/
|
|
1002
1002
|
this.commands.logout = (socket, callback) => {
|
|
1003
|
+
// The session that has to be destroyed. `socket.id` must not be used for that:
|
|
1004
|
+
// it is only a transport identifier, generated per connection by @iobroker/ws-server,
|
|
1005
|
+
// and never a session id.
|
|
1006
|
+
const sessionID = socket._sessionID || socket.conn.request.sessionID || undefined;
|
|
1003
1007
|
// try to extract access token
|
|
1004
1008
|
let accessToken;
|
|
1005
1009
|
if (socket.conn.request.headers?.authorization?.startsWith('Bearer ')) {
|
|
@@ -1024,8 +1028,8 @@ class SocketCommands {
|
|
|
1024
1028
|
if (token?.aToken) {
|
|
1025
1029
|
void this.adapter.destroySession(`a:${token.aToken}`, () => {
|
|
1026
1030
|
void this.adapter.destroySession(`r:${token.rToken}`, () => {
|
|
1027
|
-
if (
|
|
1028
|
-
void this.adapter.destroySession(
|
|
1031
|
+
if (sessionID) {
|
|
1032
|
+
void this.adapter.destroySession(sessionID, callback);
|
|
1029
1033
|
}
|
|
1030
1034
|
else if (callback) {
|
|
1031
1035
|
callback();
|
|
@@ -1034,8 +1038,8 @@ class SocketCommands {
|
|
|
1034
1038
|
});
|
|
1035
1039
|
}
|
|
1036
1040
|
else {
|
|
1037
|
-
if (
|
|
1038
|
-
void this.adapter.destroySession(
|
|
1041
|
+
if (sessionID) {
|
|
1042
|
+
void this.adapter.destroySession(sessionID, callback);
|
|
1039
1043
|
}
|
|
1040
1044
|
else if (callback) {
|
|
1041
1045
|
callback();
|
|
@@ -1043,8 +1047,8 @@ class SocketCommands {
|
|
|
1043
1047
|
}
|
|
1044
1048
|
});
|
|
1045
1049
|
}
|
|
1046
|
-
else if (
|
|
1047
|
-
void this.adapter.destroySession(
|
|
1050
|
+
else if (sessionID) {
|
|
1051
|
+
void this.adapter.destroySession(sessionID, callback);
|
|
1048
1052
|
}
|
|
1049
1053
|
else if (callback) {
|
|
1050
1054
|
callback(new Error('No session'));
|