@nocobase/auth 1.6.0-beta.9 → 1.7.0-alpha.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 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
@@ -64,6 +64,9 @@ const _Auth = class _Auth {
64
64
  this.ctx = ctx;
65
65
  }
66
66
  async skipCheck() {
67
+ if (this.ctx.skipAuthCheck === true) {
68
+ return true;
69
+ }
67
70
  const token = this.ctx.getBearerToken();
68
71
  if (!token && this.ctx.app.options.acl === false) {
69
72
  return true;
@@ -35,8 +35,17 @@ 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>;
48
+ signNewToken(userId: number): Promise<string>;
40
49
  signIn(): Promise<{
41
50
  user: Model<any, any>;
42
51
  token: string;
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 check() {
84
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
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 tokenPolicy = await this.tokenController.getConfig();
111
- if (signInTime && Date.now() - signInTime > tokenPolicy.sessionExpirationTime) {
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("Your session has expired. Please sign in again.", { ns: localeNamespace }),
114
- code: import_auth.AuthErrorCode.EXPIRED_SESSION
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 (tokenStatus === "valid" && Date.now() - iat * 1e3 > tokenPolicy.tokenExpirationTime) {
118
- tokenStatus = "expired";
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 (roleName) {
128
- this.ctx.headers["x-role"] = roleName;
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 cache = this.ctx.cache;
131
- const user = await cache.wrap(
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.INVALID_TOKEN
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
- url: this.ctx.originalUrl,
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 = ((_e = (_d = (_c = this.ctx) == null ? void 0 : _c.req) == null ? void 0 : _d.headers) == null ? void 0 : _e.accept) === "text/event-stream";
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
- url: this.ctx.originalUrl,
182
- headers: JSON.stringify((_g = (_f = this.ctx) == null ? void 0 : _f.req) == null ? void 0 : _g.headers)
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.info("token renew failed", {
227
+ this.ctx.logger.error("token renew failed", {
193
228
  method: "auth.check",
194
- url: this.ctx.originalUrl,
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, {
@@ -207,6 +240,23 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
207
240
  async validate() {
208
241
  return null;
209
242
  }
243
+ async signNewToken(userId) {
244
+ const tokenInfo = await this.tokenController.add({ userId });
245
+ const expiresIn = Math.floor((await this.tokenController.getConfig()).tokenExpirationTime / 1e3);
246
+ const token = this.jwt.sign(
247
+ {
248
+ userId,
249
+ temp: true,
250
+ iat: Math.floor(tokenInfo.issuedTime / 1e3),
251
+ signInTime: tokenInfo.signInTime
252
+ },
253
+ {
254
+ jwtid: tokenInfo.jti,
255
+ expiresIn
256
+ }
257
+ );
258
+ return token;
259
+ }
210
260
  async signIn() {
211
261
  let user;
212
262
  try {
@@ -222,20 +272,7 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
222
272
  code: import_auth.AuthErrorCode.NOT_EXIST_USER
223
273
  });
224
274
  }
225
- const tokenInfo = await this.tokenController.add({ userId: user.id });
226
- const expiresIn = Math.floor((await this.tokenController.getConfig()).tokenExpirationTime / 1e3);
227
- const token = this.jwt.sign(
228
- {
229
- userId: user.id,
230
- temp: true,
231
- iat: Math.floor(tokenInfo.issuedTime / 1e3),
232
- signInTime: tokenInfo.signInTime
233
- },
234
- {
235
- jwtid: tokenInfo.jti,
236
- expiresIn
237
- }
238
- );
275
+ const token = await this.signNewToken(user.id);
239
276
  return {
240
277
  user,
241
278
  token
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@nocobase/auth",
3
- "version": "1.6.0-beta.9",
3
+ "version": "1.7.0-alpha.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.0-beta.9",
10
- "@nocobase/cache": "1.6.0-beta.9",
11
- "@nocobase/database": "1.6.0-beta.9",
12
- "@nocobase/resourcer": "1.6.0-beta.9",
13
- "@nocobase/utils": "1.6.0-beta.9",
9
+ "@nocobase/actions": "1.7.0-alpha.1",
10
+ "@nocobase/cache": "1.7.0-alpha.1",
11
+ "@nocobase/database": "1.7.0-alpha.1",
12
+ "@nocobase/resourcer": "1.7.0-alpha.1",
13
+ "@nocobase/utils": "1.7.0-alpha.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": "eb1ff948fcf7a51175626a1a56a8b8d9b90be006"
22
+ "gitHead": "e411c9728b4d1f16b0beac16e40dd3499352b052"
23
23
  }