@0xchain/token 1.1.0-beta.61 → 1.1.0-beta.62
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/cookieSecure.d.ts +12 -0
- package/dist/cookieSecure.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -10
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 计算写 cookie 时的 secure 属性。
|
|
3
|
+
*
|
|
4
|
+
* 关键点:客户端(浏览器)以当前页面协议为准——https 页面就必须写 secure cookie,
|
|
5
|
+
* 否则会与服务端写入的 secure 同名 cookie 冲突,导航/刷新后客户端读不到。
|
|
6
|
+
* 这能让本地通过 https 代理调试时与线上行为一致。
|
|
7
|
+
*
|
|
8
|
+
* 服务端(无 window)无法感知页面协议,沿用 NODE_ENV==='production' 判断,
|
|
9
|
+
* 与既有线上行为保持一致。
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveCookieSecure(): boolean;
|
|
12
|
+
//# sourceMappingURL=cookieSecure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookieSecure.d.ts","sourceRoot":"","sources":["../src/cookieSecure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAU7C"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AA2E9D;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,qBAAqB,EAAE,WAAW,YAAY,GAAG,IAAI,KAAG,YAAY,GAAG,IA0CpG,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,WAEpC,CAAA;AAED,sCAAsC;AACtC,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,GACX,qBAAqB,GAAG,IAAI,CAc9B;AAED,eAAO,MAAM,cAAc,YAM1B,CAAA;AAID,eAAO,MAAM,cAAc,wBAgD1B,CAAA;AACD,QAAA,MAAM,YAAY,EAAE,aAMnB,CAAA;AAED,eAAe,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,41 +1,71 @@
|
|
|
1
1
|
import Cookies from "js-cookie";
|
|
2
|
+
function resolveCookieSecure() {
|
|
3
|
+
if (typeof window !== "undefined" && window.location) {
|
|
4
|
+
return window.location.protocol === "https:";
|
|
5
|
+
}
|
|
6
|
+
const authUrl = process.env.NEXT_PUBLIC_AUTH_URL || "";
|
|
7
|
+
const appUrl = process.env.NEXT_PUBLIC_APP_URL || "";
|
|
8
|
+
if (authUrl.startsWith("https://") || appUrl.startsWith("https://")) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return process.env.NODE_ENV === "production";
|
|
12
|
+
}
|
|
2
13
|
const COOKIE_DOMAIN = ".ichatgo.ai";
|
|
3
14
|
const COOKIE_PATH = "/";
|
|
4
15
|
const COOKIE_SAME_SITE = "lax";
|
|
5
|
-
const COOKIE_SECURE = process.env.NODE_ENV === "production";
|
|
6
16
|
const REFRESH_TOKEN_COOKIE_DAYS = 7;
|
|
7
17
|
function expiresFromSeconds(seconds) {
|
|
8
18
|
return new Date(Date.now() + Math.max(seconds, 0) * 1e3);
|
|
9
19
|
}
|
|
20
|
+
function decodeJwtExpiryMs(token) {
|
|
21
|
+
if (!token) return void 0;
|
|
22
|
+
const parts = token.split(".");
|
|
23
|
+
if (parts.length < 2) return void 0;
|
|
24
|
+
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
25
|
+
try {
|
|
26
|
+
const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
|
|
27
|
+
const raw = typeof atob === "function" ? atob(padded) : Buffer.from(padded, "base64").toString("binary");
|
|
28
|
+
const utf8 = decodeURIComponent(
|
|
29
|
+
raw.split("").map((c) => `%${c.charCodeAt(0).toString(16).padStart(2, "0")}`).join("")
|
|
30
|
+
);
|
|
31
|
+
const payload = JSON.parse(utf8);
|
|
32
|
+
if (typeof payload.exp === "number") {
|
|
33
|
+
return payload.exp * 1e3;
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
10
39
|
const cookieSetToken = (data) => {
|
|
11
40
|
const expiresIn = data?.expires_in ?? 3600;
|
|
12
41
|
const accessExpires = expiresFromSeconds(expiresIn);
|
|
42
|
+
const secure = resolveCookieSecure();
|
|
13
43
|
Cookies.set("access_token", data?.access_token, {
|
|
14
44
|
expires: accessExpires,
|
|
15
45
|
domain: COOKIE_DOMAIN,
|
|
16
46
|
sameSite: COOKIE_SAME_SITE,
|
|
17
|
-
secure
|
|
47
|
+
secure,
|
|
18
48
|
path: COOKIE_PATH
|
|
19
49
|
});
|
|
20
50
|
Cookies.set("refresh_token", data?.refresh_token, {
|
|
21
51
|
expires: REFRESH_TOKEN_COOKIE_DAYS,
|
|
22
52
|
domain: COOKIE_DOMAIN,
|
|
23
53
|
sameSite: COOKIE_SAME_SITE,
|
|
24
|
-
secure
|
|
54
|
+
secure,
|
|
25
55
|
path: COOKIE_PATH
|
|
26
56
|
});
|
|
27
57
|
Cookies.set("id_token", data?.id_token, {
|
|
28
58
|
expires: accessExpires,
|
|
29
59
|
domain: COOKIE_DOMAIN,
|
|
30
60
|
sameSite: COOKIE_SAME_SITE,
|
|
31
|
-
secure
|
|
61
|
+
secure,
|
|
32
62
|
path: COOKIE_PATH
|
|
33
63
|
});
|
|
34
64
|
Cookies.set("token_expire", (Date.now() + expiresIn * 1e3).toString(), {
|
|
35
65
|
expires: accessExpires,
|
|
36
66
|
domain: COOKIE_DOMAIN,
|
|
37
67
|
sameSite: COOKIE_SAME_SITE,
|
|
38
|
-
secure
|
|
68
|
+
secure,
|
|
39
69
|
path: COOKIE_PATH
|
|
40
70
|
});
|
|
41
71
|
};
|
|
@@ -44,12 +74,13 @@ const setToken = (res, response) => {
|
|
|
44
74
|
cookieSetToken(res);
|
|
45
75
|
return null;
|
|
46
76
|
} else {
|
|
77
|
+
const secure = resolveCookieSecure();
|
|
47
78
|
response.cookies.set("access_token", res?.access_token, {
|
|
48
79
|
httpOnly: false,
|
|
49
80
|
maxAge: res?.expires_in,
|
|
50
81
|
domain: COOKIE_DOMAIN,
|
|
51
82
|
sameSite: COOKIE_SAME_SITE,
|
|
52
|
-
secure
|
|
83
|
+
secure,
|
|
53
84
|
path: COOKIE_PATH
|
|
54
85
|
});
|
|
55
86
|
response.cookies.set("refresh_token", res?.refresh_token, {
|
|
@@ -57,7 +88,7 @@ const setToken = (res, response) => {
|
|
|
57
88
|
maxAge: 60 * 60 * 24 * 7,
|
|
58
89
|
domain: COOKIE_DOMAIN,
|
|
59
90
|
sameSite: COOKIE_SAME_SITE,
|
|
60
|
-
secure
|
|
91
|
+
secure,
|
|
61
92
|
path: COOKIE_PATH
|
|
62
93
|
});
|
|
63
94
|
response.cookies.set("id_token", res?.id_token, {
|
|
@@ -65,7 +96,7 @@ const setToken = (res, response) => {
|
|
|
65
96
|
maxAge: res?.expires_in,
|
|
66
97
|
domain: COOKIE_DOMAIN,
|
|
67
98
|
sameSite: COOKIE_SAME_SITE,
|
|
68
|
-
secure
|
|
99
|
+
secure,
|
|
69
100
|
path: COOKIE_PATH
|
|
70
101
|
});
|
|
71
102
|
response.cookies.set("token_expire", (Date.now() + res?.expires_in * 1e3).toString(), {
|
|
@@ -73,7 +104,7 @@ const setToken = (res, response) => {
|
|
|
73
104
|
maxAge: res?.expires_in,
|
|
74
105
|
domain: COOKIE_DOMAIN,
|
|
75
106
|
sameSite: COOKIE_SAME_SITE,
|
|
76
|
-
secure
|
|
107
|
+
secure,
|
|
77
108
|
path: COOKIE_PATH
|
|
78
109
|
});
|
|
79
110
|
}
|
|
@@ -130,10 +161,14 @@ const isTokenExpired = async () => {
|
|
|
130
161
|
}
|
|
131
162
|
const nearExpiry = (expireAt) => expireAt - Date.now() < 5 * 60 * 1e3;
|
|
132
163
|
if (accessToken) {
|
|
164
|
+
const jwtExpiry = decodeJwtExpiryMs(accessToken);
|
|
165
|
+
if (jwtExpiry) {
|
|
166
|
+
return nearExpiry(jwtExpiry);
|
|
167
|
+
}
|
|
133
168
|
if (t && !Number.isNaN(t)) {
|
|
134
169
|
return nearExpiry(t);
|
|
135
170
|
}
|
|
136
|
-
return
|
|
171
|
+
return Boolean(refreshToken);
|
|
137
172
|
}
|
|
138
173
|
if (refreshToken) {
|
|
139
174
|
return true;
|