@tachybase/auth 0.23.58 → 1.0.6

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.
@@ -3,6 +3,7 @@ import { Registry } from '@tachybase/utils';
3
3
  import { Auth, AuthExtend } from './auth';
4
4
  import { JwtOptions, JwtService } from './base/jwt-service';
5
5
  import { ITokenBlacklistService } from './base/token-blacklist-service';
6
+ import { ITokenControlService } from './base/token-control-service';
6
7
  export interface Authenticator {
7
8
  authType: string;
8
9
  options: Record<string, any>;
@@ -19,15 +20,18 @@ export type AuthManagerOptions = {
19
20
  type AuthConfig = {
20
21
  auth: AuthExtend<Auth>;
21
22
  title?: string;
23
+ getPublicOptions?: (options: Record<string, any>) => Record<string, any>;
22
24
  };
23
25
  export declare class AuthManager {
24
26
  jwt: JwtService;
27
+ tokenController: ITokenControlService;
25
28
  protected options: AuthManagerOptions;
26
29
  protected authTypes: Registry<AuthConfig>;
27
30
  protected storer: Storer;
28
31
  constructor(options: AuthManagerOptions);
29
32
  setStorer(storer: Storer): void;
30
33
  setTokenBlacklistService(service: ITokenBlacklistService): void;
34
+ setTokenControlService(service: ITokenControlService): void;
31
35
  /**
32
36
  * registerTypes
33
37
  * @description Add a new authenticate type and the corresponding authenticator.
@@ -51,7 +55,7 @@ export declare class AuthManager {
51
55
  get(name: string, ctx: Context): Promise<Auth>;
52
56
  /**
53
57
  * middleware
54
- * @description Auth middleware, used to check the authentication status.
58
+ * @description Auth middleware, used to check the user status.
55
59
  */
56
60
  middleware(): (ctx: Context & {
57
61
  auth: Auth;
@@ -35,6 +35,9 @@ const _AuthManager = class _AuthManager {
35
35
  setTokenBlacklistService(service) {
36
36
  this.jwt.blacklist = service;
37
37
  }
38
+ setTokenControlService(service) {
39
+ this.tokenController = service;
40
+ }
38
41
  /**
39
42
  * registerTypes
40
43
  * @description Add a new authenticate type and the corresponding authenticator.
@@ -77,16 +80,12 @@ const _AuthManager = class _AuthManager {
77
80
  }
78
81
  /**
79
82
  * middleware
80
- * @description Auth middleware, used to check the authentication status.
83
+ * @description Auth middleware, used to check the user status.
81
84
  */
82
85
  middleware() {
83
- return async (ctx, next) => {
84
- var _a;
85
- const token = ctx.getBearerToken();
86
- if (token && await ((_a = ctx.app.authManager.jwt.blacklist) == null ? void 0 : _a.has(token))) {
87
- return ctx.throw(403, ctx.t("token is not available"));
88
- }
89
- const name = ctx.get(this.options.authKey) || this.options.default;
86
+ const self = this;
87
+ return /* @__PURE__ */ __name(async function AuthManagerMiddleware(ctx, next) {
88
+ const name = ctx.get(self.options.authKey) || self.options.default;
90
89
  let authenticator;
91
90
  try {
92
91
  authenticator = await ctx.app.authManager.get(name, ctx);
@@ -96,14 +95,18 @@ const _AuthManager = class _AuthManager {
96
95
  ctx.logger.warn(err.message, { method: "check", authenticator: name });
97
96
  return next();
98
97
  }
99
- if (authenticator) {
100
- const user = await ctx.auth.check();
101
- if (user) {
102
- ctx.auth.user = user;
103
- }
98
+ if (!authenticator) {
99
+ return next();
100
+ }
101
+ if (await ctx.auth.skipCheck()) {
102
+ return next();
103
+ }
104
+ const user = await ctx.auth.check();
105
+ if (user) {
106
+ ctx.auth.user = user;
104
107
  }
105
108
  await next();
106
- };
109
+ }, "AuthManagerMiddleware");
107
110
  }
108
111
  async getOptions(name) {
109
112
  const authenticator = await this.storer.get(name);
package/lib/auth.d.ts CHANGED
@@ -8,6 +8,24 @@ export type AuthConfig = {
8
8
  };
9
9
  ctx: Context;
10
10
  };
11
+ export declare const AuthErrorCode: {
12
+ EMPTY_TOKEN: "EMPTY_TOKEN";
13
+ EXPIRED_TOKEN: "EXPIRED_TOKEN";
14
+ INVALID_TOKEN: "INVALID_TOKEN";
15
+ TOKEN_RENEW_FAILED: "TOKEN_RENEW_FAILED";
16
+ BLOCKED_TOKEN: "BLOCKED_TOKEN";
17
+ EXPIRED_SESSION: "EXPIRED_SESSION";
18
+ NOT_EXIST_USER: "NOT_EXIST_USER";
19
+ SKIP_TOKEN_RENEW: "SKIP_TOKEN_RENEW";
20
+ };
21
+ export type AuthErrorType = keyof typeof AuthErrorCode;
22
+ export declare class AuthError extends Error {
23
+ code: AuthErrorType;
24
+ constructor(options: {
25
+ code: AuthErrorType;
26
+ message: string;
27
+ });
28
+ }
11
29
  export type AuthExtend<T extends Auth> = new (config: AuthConfig) => T;
12
30
  interface IAuth {
13
31
  user: Model;
@@ -28,7 +46,16 @@ export declare abstract class Auth implements IAuth {
28
46
  };
29
47
  protected ctx: Context;
30
48
  constructor(config: AuthConfig);
49
+ skipCheck(): Promise<any>;
31
50
  abstract check(): Promise<Model>;
51
+ abstract checkToken(): Promise<{
52
+ tokenStatus: 'valid' | 'expired' | 'invalid';
53
+ user: Awaited<ReturnType<Auth['check']>>;
54
+ jti?: string;
55
+ temp: any;
56
+ roleName?: any;
57
+ signInTime?: number;
58
+ }>;
32
59
  signIn(): Promise<any>;
33
60
  signUp(): Promise<any>;
34
61
  signOut(): Promise<any>;
package/lib/auth.js CHANGED
@@ -18,9 +18,29 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var auth_exports = {};
20
20
  __export(auth_exports, {
21
- Auth: () => Auth
21
+ Auth: () => Auth,
22
+ AuthError: () => AuthError,
23
+ AuthErrorCode: () => AuthErrorCode
22
24
  });
23
25
  module.exports = __toCommonJS(auth_exports);
26
+ const AuthErrorCode = {
27
+ EMPTY_TOKEN: "EMPTY_TOKEN",
28
+ EXPIRED_TOKEN: "EXPIRED_TOKEN",
29
+ INVALID_TOKEN: "INVALID_TOKEN",
30
+ TOKEN_RENEW_FAILED: "TOKEN_RENEW_FAILED",
31
+ BLOCKED_TOKEN: "BLOCKED_TOKEN",
32
+ EXPIRED_SESSION: "EXPIRED_SESSION",
33
+ NOT_EXIST_USER: "NOT_EXIST_USER",
34
+ SKIP_TOKEN_RENEW: "SKIP_TOKEN_RENEW"
35
+ };
36
+ const _AuthError = class _AuthError extends Error {
37
+ constructor(options) {
38
+ super(options.message);
39
+ this.code = options.code;
40
+ }
41
+ };
42
+ __name(_AuthError, "AuthError");
43
+ let AuthError = _AuthError;
24
44
  const _Auth = class _Auth {
25
45
  constructor(config) {
26
46
  const { authenticator, options, ctx } = config;
@@ -28,6 +48,16 @@ const _Auth = class _Auth {
28
48
  this.options = options;
29
49
  this.ctx = ctx;
30
50
  }
51
+ async skipCheck() {
52
+ const token = this.ctx.getBearerToken();
53
+ if (!token && this.ctx.app.options.acl === false) {
54
+ return true;
55
+ }
56
+ const { resourceName, actionName } = this.ctx.action;
57
+ const acl = this.ctx.dataSource.acl;
58
+ const isPublic = await acl.allowManager.isAllowed(resourceName, actionName, this.ctx);
59
+ return isPublic;
60
+ }
31
61
  // The following methods are mainly designed for user authentications.
32
62
  async signIn() {
33
63
  }
@@ -40,5 +70,7 @@ __name(_Auth, "Auth");
40
70
  let Auth = _Auth;
41
71
  // Annotate the CommonJS export names for ESM import in node:
42
72
  0 && (module.exports = {
43
- Auth
73
+ Auth,
74
+ AuthError,
75
+ AuthErrorCode
44
76
  });
@@ -1,6 +1,7 @@
1
1
  import { Collection, Model } from '@tachybase/database';
2
2
  import { Auth, AuthConfig } from '../auth';
3
3
  import { JwtService } from './jwt-service';
4
+ import { ITokenControlService } from './token-control-service';
4
5
  /**
5
6
  * BaseAuth
6
7
  * @description A base class with jwt provide some common methods.
@@ -12,12 +13,22 @@ export declare class BaseAuth extends Auth {
12
13
  });
13
14
  get userRepository(): import("@tachybase/database").Repository<any, any>;
14
15
  get jwt(): JwtService;
16
+ get tokenController(): ITokenControlService;
15
17
  set user(user: Model);
16
18
  get user(): Model;
17
19
  getCacheKey(userId: number): string;
18
20
  validateUsername(username: string): boolean;
19
- check(): Promise<any>;
21
+ checkToken(): Promise<{
22
+ tokenStatus: 'valid' | 'expired' | 'invalid';
23
+ user: Awaited<ReturnType<Auth['check']>>;
24
+ jti?: string;
25
+ temp: any;
26
+ roleName?: any;
27
+ signInTime?: number;
28
+ }>;
29
+ check(): ReturnType<Auth['check']>;
20
30
  validate(): Promise<Model>;
31
+ signNewToken(userId: number): Promise<string>;
21
32
  signIn(): Promise<{
22
33
  user: Model<any, any>;
23
34
  token: string;
package/lib/base/auth.js CHANGED
@@ -1,6 +1,8 @@
1
+ var __create = Object.create;
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
8
  var __export = (target, all) => {
@@ -15,13 +17,23 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var auth_exports = {};
20
30
  __export(auth_exports, {
21
31
  BaseAuth: () => BaseAuth
22
32
  });
23
33
  module.exports = __toCommonJS(auth_exports);
34
+ var import_jsonwebtoken = __toESM(require("jsonwebtoken"));
24
35
  var import_auth = require("../auth");
36
+ const localeNamespace = "auth";
25
37
  const _BaseAuth = class _BaseAuth extends import_auth.Auth {
26
38
  constructor(config) {
27
39
  const { userCollection } = config;
@@ -34,6 +46,9 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
34
46
  get jwt() {
35
47
  return this.ctx.app.authManager.jwt;
36
48
  }
49
+ get tokenController() {
50
+ return this.ctx.app.authManager.tokenController;
51
+ }
37
52
  set user(user) {
38
53
  this.ctx.state.currentUser = user;
39
54
  }
@@ -46,47 +61,198 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
46
61
  validateUsername(username) {
47
62
  return /^[^@.<>"'/]{2,16}$/.test(username);
48
63
  }
49
- async check() {
64
+ async checkToken() {
65
+ var _a, _b, _c;
50
66
  const token = this.ctx.getBearerToken();
51
67
  if (!token) {
52
- return null;
68
+ this.ctx.throw(401, {
69
+ message: this.ctx.t("Unauthenticated. Please sign in to continue.", { ns: localeNamespace }),
70
+ code: import_auth.AuthErrorCode.EMPTY_TOKEN
71
+ });
53
72
  }
73
+ let tokenStatus;
74
+ let payload;
54
75
  try {
55
- const { userId, roleName } = await this.jwt.decode(token);
56
- if (roleName) {
57
- this.ctx.headers["x-role"] = roleName;
58
- }
59
- const cache = this.ctx.cache;
60
- return await cache.wrap(
61
- this.getCacheKey(userId),
62
- () => this.userRepository.findOne({
63
- filter: {
64
- id: userId
65
- },
66
- raw: true
67
- })
68
- );
76
+ payload = await this.jwt.decode(token);
77
+ tokenStatus = "valid";
69
78
  } catch (err) {
70
- this.ctx.logger.error(err, { method: "check" });
71
- return null;
79
+ if (err.name === "TokenExpiredError") {
80
+ tokenStatus = "expired";
81
+ payload = import_jsonwebtoken.default.decode(token);
82
+ } else {
83
+ this.ctx.logger.error(err, { method: "jwt.decode" });
84
+ this.ctx.throw(401, {
85
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
86
+ code: import_auth.AuthErrorCode.INVALID_TOKEN
87
+ });
88
+ }
89
+ }
90
+ const { userId, roleName, iat, temp, jti, exp, signInTime } = payload ?? {};
91
+ const user = userId ? await this.ctx.app.cache.wrap(
92
+ this.getCacheKey(userId),
93
+ () => this.userRepository.findOne({
94
+ filter: {
95
+ id: userId
96
+ },
97
+ raw: true
98
+ })
99
+ ) : null;
100
+ if (!user) {
101
+ this.ctx.throw(401, {
102
+ message: this.ctx.t("User not found. Please sign in again to continue.", { ns: localeNamespace }),
103
+ code: import_auth.AuthErrorCode.NOT_EXIST_USER
104
+ });
105
+ }
106
+ if (roleName) {
107
+ this.ctx.headers["x-role"] = roleName;
72
108
  }
109
+ const blocked = await this.jwt.blacklist.has(jti ?? token);
110
+ if (blocked) {
111
+ this.ctx.throw(401, {
112
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
113
+ code: import_auth.AuthErrorCode.BLOCKED_TOKEN
114
+ });
115
+ }
116
+ if (!temp) {
117
+ if (tokenStatus === "valid") {
118
+ return { tokenStatus, user, temp };
119
+ } else {
120
+ this.ctx.throw(401, {
121
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
122
+ code: import_auth.AuthErrorCode.INVALID_TOKEN
123
+ });
124
+ }
125
+ }
126
+ const tokenPolicy = await this.tokenController.getConfig();
127
+ if (signInTime && Date.now() - signInTime > tokenPolicy.sessionExpirationTime) {
128
+ this.ctx.throw(401, {
129
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
130
+ code: import_auth.AuthErrorCode.EXPIRED_SESSION
131
+ });
132
+ }
133
+ if (tokenStatus === "valid" && Date.now() - iat * 1e3 > tokenPolicy.tokenExpirationTime) {
134
+ tokenStatus = "expired";
135
+ }
136
+ if (tokenStatus === "valid" && user.passwordChangeTz && iat * 1e3 < user.passwordChangeTz) {
137
+ this.ctx.throw(401, {
138
+ message: this.ctx.t("User password changed, please signin again.", { ns: localeNamespace }),
139
+ code: import_auth.AuthErrorCode.INVALID_TOKEN
140
+ });
141
+ }
142
+ if (tokenStatus === "expired") {
143
+ if (tokenPolicy.expiredTokenRenewLimit > 0 && Date.now() - exp * 1e3 > tokenPolicy.expiredTokenRenewLimit) {
144
+ this.ctx.throw(401, {
145
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
146
+ code: import_auth.AuthErrorCode.EXPIRED_SESSION
147
+ });
148
+ }
149
+ this.ctx.logger.info("token renewing", {
150
+ method: "auth.check",
151
+ url: this.ctx.originalUrl,
152
+ currentJti: jti
153
+ });
154
+ 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";
155
+ if (isStreamRequest) {
156
+ this.ctx.throw(401, {
157
+ message: "Stream api not allow renew token.",
158
+ code: import_auth.AuthErrorCode.SKIP_TOKEN_RENEW
159
+ });
160
+ }
161
+ if (!jti) {
162
+ this.ctx.throw(401, {
163
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
164
+ code: import_auth.AuthErrorCode.INVALID_TOKEN
165
+ });
166
+ }
167
+ return { tokenStatus, user, jti, signInTime, temp };
168
+ }
169
+ return { tokenStatus, user, jti, signInTime, temp };
170
+ }
171
+ async check() {
172
+ var _a, _b, _c;
173
+ const { tokenStatus, user, jti, temp, signInTime, roleName } = await this.checkToken();
174
+ if (tokenStatus === "expired") {
175
+ const tokenPolicy = await this.tokenController.getConfig();
176
+ try {
177
+ this.ctx.logger.info("token renewing", {
178
+ method: "auth.check",
179
+ jti
180
+ });
181
+ 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";
182
+ if (isStreamRequest) {
183
+ this.ctx.throw(401, {
184
+ message: "Stream api not allow renew token.",
185
+ code: import_auth.AuthErrorCode.SKIP_TOKEN_RENEW
186
+ });
187
+ }
188
+ if (!jti) {
189
+ this.ctx.throw(401, {
190
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
191
+ code: import_auth.AuthErrorCode.INVALID_TOKEN
192
+ });
193
+ }
194
+ const renewedResult = await this.tokenController.renew(jti);
195
+ this.ctx.logger.info("token renewed", {
196
+ method: "auth.check",
197
+ oldJti: jti,
198
+ newJti: renewedResult.jti
199
+ });
200
+ const expiresIn = Math.floor(tokenPolicy.tokenExpirationTime / 1e3);
201
+ const newToken = this.jwt.sign(
202
+ { userId: user.id, roleName, temp, signInTime, iat: Math.floor(renewedResult.issuedTime / 1e3) },
203
+ { jwtid: renewedResult.jti, expiresIn }
204
+ );
205
+ this.ctx.res.setHeader("x-new-token", newToken);
206
+ } catch (err) {
207
+ this.ctx.logger.error("token renew failed", {
208
+ method: "auth.check",
209
+ jti
210
+ });
211
+ const options = err instanceof import_auth.AuthError ? { code: err.code, message: err.message } : { message: err.message, code: err.code ?? import_auth.AuthErrorCode.INVALID_TOKEN };
212
+ this.ctx.throw(401, {
213
+ message: this.ctx.t(options.message, { ns: localeNamespace }),
214
+ code: options.code
215
+ });
216
+ }
217
+ }
218
+ return user;
73
219
  }
74
220
  async validate() {
75
221
  return null;
76
222
  }
223
+ async signNewToken(userId) {
224
+ const tokenInfo = await this.tokenController.add({ userId });
225
+ const expiresIn = Math.floor((await this.tokenController.getConfig()).tokenExpirationTime / 1e3);
226
+ const token = this.jwt.sign(
227
+ {
228
+ userId,
229
+ temp: true,
230
+ iat: Math.floor(tokenInfo.issuedTime / 1e3),
231
+ signInTime: tokenInfo.signInTime
232
+ },
233
+ {
234
+ jwtid: tokenInfo.jti,
235
+ expiresIn
236
+ }
237
+ );
238
+ return token;
239
+ }
77
240
  async signIn() {
78
241
  let user;
79
242
  try {
80
243
  user = await this.validate();
81
244
  } catch (err) {
82
- this.ctx.throw(401, err.message);
245
+ this.ctx.throw(err.status || 401, err.message, {
246
+ ...err
247
+ });
83
248
  }
84
249
  if (!user) {
85
- this.ctx.throw(401, "Unauthorized");
250
+ this.ctx.throw(401, {
251
+ message: this.ctx.t("User not found. Please sign in again to continue.", { ns: localeNamespace }),
252
+ code: import_auth.AuthErrorCode.NOT_EXIST_USER
253
+ });
86
254
  }
87
- const token = this.jwt.sign({
88
- userId: user.id
89
- });
255
+ const token = await this.signNewToken(user.id);
90
256
  return {
91
257
  user,
92
258
  token
@@ -97,8 +263,24 @@ const _BaseAuth = class _BaseAuth extends import_auth.Auth {
97
263
  if (!token) {
98
264
  return;
99
265
  }
100
- const { userId } = await this.jwt.decode(token);
101
- await this.ctx.app.emitAsync("beforeSignOut", { userId });
266
+ let userId;
267
+ try {
268
+ const result = await this.jwt.decode(token);
269
+ userId = result.userId;
270
+ } catch (err) {
271
+ if (err.name === "TokenExpiredError") {
272
+ this.ctx.throw(401, {
273
+ message: this.ctx.t("Your session has expired. Please sign in again.", { ns: localeNamespace }),
274
+ code: import_auth.AuthErrorCode.INVALID_TOKEN
275
+ });
276
+ } else {
277
+ this.ctx.throw(401, {
278
+ message: this.ctx.t("Invalid token. Please sign in again.", { ns: localeNamespace }),
279
+ code: import_auth.AuthErrorCode.INVALID_TOKEN
280
+ });
281
+ }
282
+ }
283
+ await this.ctx.app.emitAsync("cache:del:roles", { userId });
102
284
  await this.ctx.cache.del(this.getCacheKey(userId));
103
285
  return await this.jwt.block(token);
104
286
  }
@@ -1,4 +1,4 @@
1
- import jwt, { SignOptions } from 'jsonwebtoken';
1
+ import jwt, { JwtPayload, SignOptions } from 'jsonwebtoken';
2
2
  import { ITokenBlacklistService } from './token-blacklist-service';
3
3
  export interface JwtOptions {
4
4
  secret: string;
@@ -12,7 +12,7 @@ export declare class JwtService {
12
12
  private expiresIn;
13
13
  private secret;
14
14
  sign(payload: SignPayload, options?: SignOptions): string;
15
- decode(token: string): Promise<any>;
15
+ decode(token: string): Promise<JwtPayload>;
16
16
  /**
17
17
  * @description Block a token so that this token can no longer be used
18
18
  */
@@ -74,9 +74,9 @@ const _JwtService = class _JwtService {
74
74
  return null;
75
75
  }
76
76
  try {
77
- const { exp } = await this.decode(token);
77
+ const { exp, jti } = await this.decode(token);
78
78
  return this.blacklist.add({
79
- token,
79
+ token: jti ?? token,
80
80
  expiration: new Date(exp * 1e3).toString()
81
81
  });
82
82
  } catch {
@@ -0,0 +1,30 @@
1
+ export interface TokenPolicyConfig {
2
+ tokenExpirationTime: string;
3
+ sessionExpirationTime: string;
4
+ expiredTokenRenewLimit: string;
5
+ }
6
+ type millisecond = number;
7
+ export type NumericTokenPolicyConfig = {
8
+ [K in keyof TokenPolicyConfig]: millisecond;
9
+ };
10
+ export type TokenInfo = {
11
+ jti: string;
12
+ userId: number;
13
+ issuedTime: EpochTimeStamp;
14
+ signInTime: EpochTimeStamp;
15
+ renewed: boolean;
16
+ };
17
+ export type JTIStatus = 'valid' | 'inactive' | 'blocked' | 'missing' | 'renewed' | 'expired';
18
+ export interface ITokenControlService {
19
+ getConfig(): Promise<NumericTokenPolicyConfig>;
20
+ setConfig(config: TokenPolicyConfig): Promise<any>;
21
+ renew(jti: string): Promise<{
22
+ jti: string;
23
+ issuedTime: EpochTimeStamp;
24
+ }>;
25
+ add({ userId }: {
26
+ userId: number;
27
+ }): Promise<TokenInfo>;
28
+ removeSessionExpiredTokens(userId: number): Promise<void>;
29
+ }
30
+ export {};
@@ -0,0 +1,15 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
14
+ var token_control_service_exports = {};
15
+ module.exports = __toCommonJS(token_control_service_exports);
package/lib/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from './auth';
3
3
  export * from './auth-manager';
4
4
  export * from './base/auth';
5
5
  export * from './base/token-blacklist-service';
6
+ export * from './base/token-control-service';
package/lib/index.js CHANGED
@@ -19,11 +19,13 @@ __reExport(src_exports, require("./auth"), module.exports);
19
19
  __reExport(src_exports, require("./auth-manager"), module.exports);
20
20
  __reExport(src_exports, require("./base/auth"), module.exports);
21
21
  __reExport(src_exports, require("./base/token-blacklist-service"), module.exports);
22
+ __reExport(src_exports, require("./base/token-control-service"), module.exports);
22
23
  // Annotate the CommonJS export names for ESM import in node:
23
24
  0 && (module.exports = {
24
25
  ...require("./actions"),
25
26
  ...require("./auth"),
26
27
  ...require("./auth-manager"),
27
28
  ...require("./base/auth"),
28
- ...require("./base/token-blacklist-service")
29
+ ...require("./base/token-blacklist-service"),
30
+ ...require("./base/token-control-service")
29
31
  });
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@tachybase/auth",
3
- "version": "0.23.58",
3
+ "version": "1.0.6",
4
4
  "description": "",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./lib/index.js",
7
7
  "types": "./lib/index.d.ts",
8
8
  "dependencies": {
9
9
  "jsonwebtoken": "^8.5.1",
10
- "@tachybase/actions": "0.23.58",
11
- "@tachybase/database": "0.23.58",
12
- "@tachybase/cache": "0.23.58",
13
- "@tachybase/resourcer": "0.23.58",
14
- "@tachybase/utils": "0.23.58"
10
+ "@tachybase/actions": "1.0.6",
11
+ "@tachybase/database": "1.0.6",
12
+ "@tachybase/resourcer": "1.0.6",
13
+ "@tachybase/utils": "1.0.6",
14
+ "@tachybase/cache": "1.0.6"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@types/jsonwebtoken": "^8.5.9",