@nocobase/auth 1.6.0-beta.9 → 1.6.1
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/lib/auth.d.ts +8 -0
- package/lib/auth.js +3 -0
- package/lib/base/auth.d.ts +8 -0
- package/lib/base/auth.js +66 -33
- package/package.json +7 -7
package/lib/auth.d.ts
CHANGED
|
@@ -56,6 +56,14 @@ export declare abstract class Auth implements IAuth {
|
|
|
56
56
|
constructor(config: AuthConfig);
|
|
57
57
|
skipCheck(): Promise<any>;
|
|
58
58
|
abstract check(): Promise<Model>;
|
|
59
|
+
abstract checkToken(): Promise<{
|
|
60
|
+
tokenStatus: 'valid' | 'expired' | 'invalid';
|
|
61
|
+
user: Awaited<ReturnType<Auth['check']>>;
|
|
62
|
+
jti?: string;
|
|
63
|
+
temp: any;
|
|
64
|
+
roleName?: any;
|
|
65
|
+
signInTime?: number;
|
|
66
|
+
}>;
|
|
59
67
|
signIn(): Promise<any>;
|
|
60
68
|
signUp(): Promise<any>;
|
|
61
69
|
signOut(): Promise<any>;
|
package/lib/auth.js
CHANGED
package/lib/base/auth.d.ts
CHANGED
|
@@ -35,6 +35,14 @@ export declare class BaseAuth extends Auth {
|
|
|
35
35
|
* @internal
|
|
36
36
|
*/
|
|
37
37
|
validateUsername(username: string): boolean;
|
|
38
|
+
checkToken(): Promise<{
|
|
39
|
+
tokenStatus: 'valid' | 'expired' | 'invalid';
|
|
40
|
+
user: Awaited<ReturnType<Auth['check']>>;
|
|
41
|
+
jti?: string;
|
|
42
|
+
temp: any;
|
|
43
|
+
roleName?: any;
|
|
44
|
+
signInTime?: number;
|
|
45
|
+
}>;
|
|
38
46
|
check(): ReturnType<Auth['check']>;
|
|
39
47
|
validate(): Promise<Model>;
|
|
40
48
|
signIn(): Promise<{
|
package/lib/base/auth.js
CHANGED
|
@@ -80,8 +80,9 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
|
|
|
80
80
|
validateUsername(username) {
|
|
81
81
|
return /^[^@.<>"'/]{1,50}$/.test(username);
|
|
82
82
|
}
|
|
83
|
-
async
|
|
84
|
-
var _a, _b, _c
|
|
83
|
+
async checkToken() {
|
|
84
|
+
var _a, _b, _c;
|
|
85
|
+
const cache = this.ctx.cache;
|
|
85
86
|
const token = this.ctx.getBearerToken();
|
|
86
87
|
if (!token) {
|
|
87
88
|
this.ctx.throw(401, {
|
|
@@ -107,15 +108,23 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
const { userId, roleName, iat, temp, jti, exp, signInTime } = payload ?? {};
|
|
110
|
-
const
|
|
111
|
-
|
|
111
|
+
const user = userId ? await cache.wrap(
|
|
112
|
+
this.getCacheKey(userId),
|
|
113
|
+
() => this.userRepository.findOne({
|
|
114
|
+
filter: {
|
|
115
|
+
id: userId
|
|
116
|
+
},
|
|
117
|
+
raw: true
|
|
118
|
+
})
|
|
119
|
+
) : null;
|
|
120
|
+
if (!user) {
|
|
112
121
|
this.ctx.throw(401, {
|
|
113
|
-
message: this.ctx.t("
|
|
114
|
-
code: import_auth.AuthErrorCode.
|
|
122
|
+
message: this.ctx.t("User not found. Please sign in again to continue.", { ns: localeNamespace }),
|
|
123
|
+
code: import_auth.AuthErrorCode.NOT_EXIST_USER
|
|
115
124
|
});
|
|
116
125
|
}
|
|
117
|
-
if (
|
|
118
|
-
|
|
126
|
+
if (roleName) {
|
|
127
|
+
this.ctx.headers["x-role"] = roleName;
|
|
119
128
|
}
|
|
120
129
|
const blocked = await this.jwt.blacklist.has(jti ?? token);
|
|
121
130
|
if (blocked) {
|
|
@@ -124,25 +133,26 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
|
|
|
124
133
|
code: import_auth.AuthErrorCode.BLOCKED_TOKEN
|
|
125
134
|
});
|
|
126
135
|
}
|
|
127
|
-
if (
|
|
128
|
-
|
|
136
|
+
if (!temp) {
|
|
137
|
+
if (tokenStatus === "valid") {
|
|
138
|
+
return { tokenStatus, user, temp };
|
|
139
|
+
} else {
|
|
140
|
+
this.ctx.throw(401, {
|
|
141
|
+
message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
|
|
142
|
+
code: import_auth.AuthErrorCode.INVALID_TOKEN
|
|
143
|
+
});
|
|
144
|
+
}
|
|
129
145
|
}
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
this.getCacheKey(userId),
|
|
133
|
-
() => this.userRepository.findOne({
|
|
134
|
-
filter: {
|
|
135
|
-
id: userId
|
|
136
|
-
},
|
|
137
|
-
raw: true
|
|
138
|
-
})
|
|
139
|
-
);
|
|
140
|
-
if (!temp && tokenStatus !== "valid") {
|
|
146
|
+
const tokenPolicy = await this.tokenController.getConfig();
|
|
147
|
+
if (signInTime && Date.now() - signInTime > tokenPolicy.sessionExpirationTime) {
|
|
141
148
|
this.ctx.throw(401, {
|
|
142
149
|
message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
|
|
143
|
-
code: import_auth.AuthErrorCode.
|
|
150
|
+
code: import_auth.AuthErrorCode.EXPIRED_SESSION
|
|
144
151
|
});
|
|
145
152
|
}
|
|
153
|
+
if (tokenStatus === "valid" && Date.now() - iat * 1e3 > tokenPolicy.tokenExpirationTime) {
|
|
154
|
+
tokenStatus = "expired";
|
|
155
|
+
}
|
|
146
156
|
if (tokenStatus === "valid" && user.passwordChangeTz && iat * 1e3 < user.passwordChangeTz) {
|
|
147
157
|
this.ctx.throw(401, {
|
|
148
158
|
message: this.ctx.t("User password changed, please signin again.", { ns: localeNamespace }),
|
|
@@ -156,13 +166,39 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
|
|
|
156
166
|
code: import_auth.AuthErrorCode.EXPIRED_SESSION
|
|
157
167
|
});
|
|
158
168
|
}
|
|
169
|
+
this.ctx.logger.info("token renewing", {
|
|
170
|
+
method: "auth.check",
|
|
171
|
+
url: this.ctx.originalUrl,
|
|
172
|
+
currentJti: jti
|
|
173
|
+
});
|
|
174
|
+
const isStreamRequest = ((_c = (_b = (_a = this.ctx) == null ? void 0 : _a.req) == null ? void 0 : _b.headers) == null ? void 0 : _c.accept) === "text/event-stream";
|
|
175
|
+
if (isStreamRequest) {
|
|
176
|
+
this.ctx.throw(401, {
|
|
177
|
+
message: "Stream api not allow renew token.",
|
|
178
|
+
code: import_auth.AuthErrorCode.SKIP_TOKEN_RENEW
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
if (!jti) {
|
|
182
|
+
this.ctx.throw(401, {
|
|
183
|
+
message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
|
|
184
|
+
code: import_auth.AuthErrorCode.INVALID_TOKEN
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return { tokenStatus, user, jti, signInTime, temp };
|
|
188
|
+
}
|
|
189
|
+
return { tokenStatus, user, jti, signInTime, temp };
|
|
190
|
+
}
|
|
191
|
+
async check() {
|
|
192
|
+
var _a, _b, _c;
|
|
193
|
+
const { tokenStatus, user, jti, temp, signInTime, roleName } = await this.checkToken();
|
|
194
|
+
if (tokenStatus === "expired") {
|
|
195
|
+
const tokenPolicy = await this.tokenController.getConfig();
|
|
159
196
|
try {
|
|
160
197
|
this.ctx.logger.info("token renewing", {
|
|
161
198
|
method: "auth.check",
|
|
162
|
-
|
|
163
|
-
headers: JSON.stringify((_b = (_a = this.ctx) == null ? void 0 : _a.req) == null ? void 0 : _b.headers)
|
|
199
|
+
jti
|
|
164
200
|
});
|
|
165
|
-
const isStreamRequest = ((
|
|
201
|
+
const isStreamRequest = ((_c = (_b = (_a = this.ctx) == null ? void 0 : _a.req) == null ? void 0 : _b.headers) == null ? void 0 : _c.accept) === "text/event-stream";
|
|
166
202
|
if (isStreamRequest) {
|
|
167
203
|
this.ctx.throw(401, {
|
|
168
204
|
message: "Stream api not allow renew token.",
|
|
@@ -178,22 +214,19 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
|
|
|
178
214
|
const renewedResult = await this.tokenController.renew(jti);
|
|
179
215
|
this.ctx.logger.info("token renewed", {
|
|
180
216
|
method: "auth.check",
|
|
181
|
-
|
|
182
|
-
|
|
217
|
+
oldJti: jti,
|
|
218
|
+
newJti: renewedResult.jti
|
|
183
219
|
});
|
|
184
220
|
const expiresIn = Math.floor(tokenPolicy.tokenExpirationTime / 1e3);
|
|
185
221
|
const newToken = this.jwt.sign(
|
|
186
|
-
{ userId, roleName, temp, signInTime, iat: Math.floor(renewedResult.issuedTime / 1e3) },
|
|
222
|
+
{ userId: user.id, roleName, temp, signInTime, iat: Math.floor(renewedResult.issuedTime / 1e3) },
|
|
187
223
|
{ jwtid: renewedResult.jti, expiresIn }
|
|
188
224
|
);
|
|
189
225
|
this.ctx.res.setHeader("x-new-token", newToken);
|
|
190
|
-
return user;
|
|
191
226
|
} catch (err) {
|
|
192
|
-
this.ctx.logger.
|
|
227
|
+
this.ctx.logger.error("token renew failed", {
|
|
193
228
|
method: "auth.check",
|
|
194
|
-
|
|
195
|
-
err,
|
|
196
|
-
headers: JSON.stringify((_i = (_h = this.ctx) == null ? void 0 : _h.req) == null ? void 0 : _i.headers)
|
|
229
|
+
jti
|
|
197
230
|
});
|
|
198
231
|
const options = err instanceof import_auth.AuthError ? { code: err.code, message: err.message } : { message: err.message, code: err.code ?? import_auth.AuthErrorCode.INVALID_TOKEN };
|
|
199
232
|
this.ctx.throw(401, {
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/auth",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"types": "./lib/index.d.ts",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@nocobase/actions": "1.6.
|
|
10
|
-
"@nocobase/cache": "1.6.
|
|
11
|
-
"@nocobase/database": "1.6.
|
|
12
|
-
"@nocobase/resourcer": "1.6.
|
|
13
|
-
"@nocobase/utils": "1.6.
|
|
9
|
+
"@nocobase/actions": "1.6.1",
|
|
10
|
+
"@nocobase/cache": "1.6.1",
|
|
11
|
+
"@nocobase/database": "1.6.1",
|
|
12
|
+
"@nocobase/resourcer": "1.6.1",
|
|
13
|
+
"@nocobase/utils": "1.6.1",
|
|
14
14
|
"@types/jsonwebtoken": "^8.5.8",
|
|
15
15
|
"jsonwebtoken": "^8.5.1"
|
|
16
16
|
},
|
|
@@ -19,5 +19,5 @@
|
|
|
19
19
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
20
20
|
"directory": "packages/auth"
|
|
21
21
|
},
|
|
22
|
-
"gitHead": "
|
|
22
|
+
"gitHead": "a784836ebbe1ddd514bf09c477ca0cff176dcbfd"
|
|
23
23
|
}
|