@hubex/mcp 0.7.0 → 0.8.0
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/CONNECTING.md +2 -0
- package/dist/auth.js +11 -1
- package/dist/http.js +5 -0
- package/package.json +1 -1
package/CONNECTING.md
CHANGED
|
@@ -92,6 +92,8 @@ npm run build
|
|
|
92
92
|
> покажут поле ввода; остальным нужно вызвать инструмент `hubex_set_token` и
|
|
93
93
|
> передать токен в него. По токену запрашивается refresh, дальше сессия
|
|
94
94
|
> продлевается сама; после перезапуска сервера токен спрашивается заново.
|
|
95
|
+
> Если HubEx отверг токен (ошибка 401), следующий запрос получит новый — по
|
|
96
|
+
> refresh, а если не выйдет, сервер снова попросит токен.
|
|
95
97
|
|
|
96
98
|
> Сервисный токен выпускается один раз администратором:
|
|
97
99
|
> `POST /fsm/AUTHZ/ServiceTokens` с Bearer и полномочием `ServiceTokenAdd`, тело — массив id
|
package/dist/auth.js
CHANGED
|
@@ -51,6 +51,11 @@ class RefreshingAuth {
|
|
|
51
51
|
prompter;
|
|
52
52
|
accessToken;
|
|
53
53
|
accessExp; // seconds since epoch
|
|
54
|
+
/**
|
|
55
|
+
* Set by `invalidate`. The rejected token is kept rather than dropped: `renew`
|
|
56
|
+
* still has to send it as `accessJwt` to preserve the token lifetime.
|
|
57
|
+
*/
|
|
58
|
+
accessRejected = false;
|
|
54
59
|
refreshToken;
|
|
55
60
|
refreshExp; // seconds since epoch
|
|
56
61
|
tenantId;
|
|
@@ -74,8 +79,12 @@ class RefreshingAuth {
|
|
|
74
79
|
this.absorb({ access_token: trimmed });
|
|
75
80
|
await this.acquireRefreshToken();
|
|
76
81
|
}
|
|
82
|
+
invalidate(token) {
|
|
83
|
+
if (token === this.accessToken)
|
|
84
|
+
this.accessRejected = true;
|
|
85
|
+
}
|
|
77
86
|
async getAccessToken() {
|
|
78
|
-
if (this.accessToken && !isExpired(this.accessExp)) {
|
|
87
|
+
if (this.accessToken && !this.accessRejected && !isExpired(this.accessExp)) {
|
|
79
88
|
return this.accessToken;
|
|
80
89
|
}
|
|
81
90
|
// De-duplicate concurrent acquisitions.
|
|
@@ -222,6 +231,7 @@ class RefreshingAuth {
|
|
|
222
231
|
absorb(result) {
|
|
223
232
|
if (result.access_token) {
|
|
224
233
|
this.accessToken = result.access_token;
|
|
234
|
+
this.accessRejected = false;
|
|
225
235
|
const claims = decodeJwt(result.access_token);
|
|
226
236
|
this.accessExp = claims?.exp;
|
|
227
237
|
if (!this.tenantId)
|
package/dist/http.js
CHANGED
|
@@ -122,6 +122,11 @@ export class HubexClient {
|
|
|
122
122
|
exposed[name] = value;
|
|
123
123
|
}
|
|
124
124
|
if (!res.ok) {
|
|
125
|
+
// 401 — токен отвергнут (отозван, другое окружение), хотя по exp ещё жив.
|
|
126
|
+
// Без сброса провайдер отдавал бы его до истечения срока, и каждый запрос
|
|
127
|
+
// падал бы так же. Сам запрос не повторяем: POST не идемпотентен.
|
|
128
|
+
if (res.status === 401)
|
|
129
|
+
this.auth.invalidate(token);
|
|
125
130
|
throw new HubexApiError(res.status, req.service, req.path, visible ?? text, this.config.env);
|
|
126
131
|
}
|
|
127
132
|
return { status: res.status, data: visible, headers: exposed };
|