@uzqw/shared 0.1.7 → 0.1.8
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/index.d.ts +12 -3
- package/dist/index.js +36 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -98,9 +98,18 @@ declare class OAuth {
|
|
|
98
98
|
private logtoClientId;
|
|
99
99
|
/** logto 模式端点校验:缺省抛错(prod 独立 Logto 未配置时明确报错,不静默连测试实例) */
|
|
100
100
|
private logtoEndpoint;
|
|
101
|
+
/** 登出后「下次登录强制重新认证」标志文件(token 文件旁,按环境/实例隔离)。
|
|
102
|
+
* 解决:logout 只删本地 token,浏览器 Logto 会话仍在 → 下次 login SSO 秒过不弹页。
|
|
103
|
+
* 置标后下次 createAuthorizationRequest 自动带 prompt=login,登录成功(exchangeCode)自动清除。 */
|
|
104
|
+
forceLoginFlagPath(): string;
|
|
105
|
+
/** 是否存在待消费的强制认证标志 */
|
|
106
|
+
isForceLoginPending(): Promise<boolean>;
|
|
107
|
+
private setForceLoginPending;
|
|
108
|
+
private clearForceLoginFlag;
|
|
101
109
|
/** 构造授权请求(PKCE S256)。extraParams 用于本地联调注入 user_id(developer 模式,env=local 才接受)
|
|
102
|
-
* 或 logto 强制重新认证 prompt=login(force 登录换号)。
|
|
103
|
-
|
|
110
|
+
* 或 logto 强制重新认证 prompt=login(force 登录换号)。
|
|
111
|
+
* 登出后遗留的强制认证标志也会自动加 prompt=login——用户无需知道 force。 */
|
|
112
|
+
createAuthorizationRequest(extraParams?: Record<string, string>): Promise<AuthorizationRequest>;
|
|
104
113
|
/** 授权码换凭证并落盘;失败抛 Error(含状态码与响应体)。
|
|
105
114
|
* developer 模式:直接换 developerOAuth JWT;
|
|
106
115
|
* logto 模式:先换 Logto access token,再 POST /open/oauth/apikey 换 sk- 长期 key(落盘的是 sk- key)。 */
|
|
@@ -111,7 +120,7 @@ declare class OAuth {
|
|
|
111
120
|
getAccessToken(): Promise<string | null>;
|
|
112
121
|
/** 服务端撤销指定 token(RFC 7009:未知 token 也返回成功)。 */
|
|
113
122
|
revoke(token: string, tokenTypeHint?: string): Promise<void>;
|
|
114
|
-
/**
|
|
123
|
+
/** 本地登出:删 token + 置「下次登录强制重新认证」标志(浏览器 Logto 会话由用户/换号时另处理)。 */
|
|
115
124
|
logout(): Promise<void>;
|
|
116
125
|
}
|
|
117
126
|
|
package/dist/index.js
CHANGED
|
@@ -109,6 +109,7 @@ var TOKENS_MCP_PATH = join2(homedir2(), ".recolx", "tokens-mcp.json");
|
|
|
109
109
|
|
|
110
110
|
// src/oauth.ts
|
|
111
111
|
import { createHash, randomBytes } from "crypto";
|
|
112
|
+
import { mkdir as mkdir2, readFile as readFile2, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
112
113
|
function generateCodeVerifier() {
|
|
113
114
|
return randomBytes(32).toString("base64url");
|
|
114
115
|
}
|
|
@@ -159,9 +160,38 @@ var OAuth = class {
|
|
|
159
160
|
}
|
|
160
161
|
return ep;
|
|
161
162
|
}
|
|
163
|
+
/** 登出后「下次登录强制重新认证」标志文件(token 文件旁,按环境/实例隔离)。
|
|
164
|
+
* 解决:logout 只删本地 token,浏览器 Logto 会话仍在 → 下次 login SSO 秒过不弹页。
|
|
165
|
+
* 置标后下次 createAuthorizationRequest 自动带 prompt=login,登录成功(exchangeCode)自动清除。 */
|
|
166
|
+
forceLoginFlagPath() {
|
|
167
|
+
return `${this.tokenStore.path}.force`;
|
|
168
|
+
}
|
|
169
|
+
/** 是否存在待消费的强制认证标志 */
|
|
170
|
+
async isForceLoginPending() {
|
|
171
|
+
try {
|
|
172
|
+
await readFile2(this.forceLoginFlagPath(), "utf8");
|
|
173
|
+
return true;
|
|
174
|
+
} catch {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async setForceLoginPending() {
|
|
179
|
+
await mkdir2(this.tokenStore.dir, { recursive: true });
|
|
180
|
+
await writeFile2(this.forceLoginFlagPath(), (/* @__PURE__ */ new Date()).toISOString() + "\n", "utf8");
|
|
181
|
+
}
|
|
182
|
+
async clearForceLoginFlag() {
|
|
183
|
+
try {
|
|
184
|
+
await rm2(this.forceLoginFlagPath());
|
|
185
|
+
} catch {
|
|
186
|
+
}
|
|
187
|
+
}
|
|
162
188
|
/** 构造授权请求(PKCE S256)。extraParams 用于本地联调注入 user_id(developer 模式,env=local 才接受)
|
|
163
|
-
* 或 logto 强制重新认证 prompt=login(force 登录换号)。
|
|
164
|
-
|
|
189
|
+
* 或 logto 强制重新认证 prompt=login(force 登录换号)。
|
|
190
|
+
* 登出后遗留的强制认证标志也会自动加 prompt=login——用户无需知道 force。 */
|
|
191
|
+
async createAuthorizationRequest(extraParams = {}) {
|
|
192
|
+
if (!extraParams.prompt && await this.isForceLoginPending()) {
|
|
193
|
+
extraParams = { ...extraParams, prompt: "login" };
|
|
194
|
+
}
|
|
165
195
|
const codeVerifier = generateCodeVerifier();
|
|
166
196
|
const state = generateState();
|
|
167
197
|
if (this.mode === "logto") {
|
|
@@ -234,6 +264,7 @@ var OAuth = class {
|
|
|
234
264
|
}
|
|
235
265
|
const tokenSet2 = { access_token: apiKey, token_type: "Bearer" };
|
|
236
266
|
await this.tokenStore.save(tokenSet2);
|
|
267
|
+
await this.clearForceLoginFlag();
|
|
237
268
|
return tokenSet2;
|
|
238
269
|
}
|
|
239
270
|
const res = await this.fetchImpl(this.tokenUrl, {
|
|
@@ -246,6 +277,7 @@ var OAuth = class {
|
|
|
246
277
|
}
|
|
247
278
|
const tokenSet = toTokenSet(await res.json());
|
|
248
279
|
await this.tokenStore.save(tokenSet);
|
|
280
|
+
await this.clearForceLoginFlag();
|
|
249
281
|
return tokenSet;
|
|
250
282
|
}
|
|
251
283
|
/** 用 refresh_token 换新 token(后端滚动轮换);logto 模式无 refresh(sk- key 长期有效),恒返回 null。 */
|
|
@@ -288,9 +320,10 @@ var OAuth = class {
|
|
|
288
320
|
body: new URLSearchParams(body)
|
|
289
321
|
});
|
|
290
322
|
}
|
|
291
|
-
/**
|
|
323
|
+
/** 本地登出:删 token + 置「下次登录强制重新认证」标志(浏览器 Logto 会话由用户/换号时另处理)。 */
|
|
292
324
|
async logout() {
|
|
293
325
|
await this.tokenStore.clear();
|
|
326
|
+
await this.setForceLoginPending();
|
|
294
327
|
}
|
|
295
328
|
};
|
|
296
329
|
|