@tstdl/base 0.90.36 → 0.90.38

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.
Files changed (25) hide show
  1. package/authentication/authentication.api.d.ts +78 -3
  2. package/authentication/authentication.api.js +26 -1
  3. package/authentication/client/authentication.service.d.ts +5 -1
  4. package/authentication/client/authentication.service.js +46 -8
  5. package/authentication/models/token-payload-base.model.d.ts +1 -0
  6. package/authentication/models/token-payload-base.model.js +5 -0
  7. package/authentication/models/token.model.d.ts +1 -0
  8. package/authentication/server/authentication-ancillary.service.d.ts +25 -0
  9. package/authentication/server/{authentication-token-payload.provider.js → authentication-ancillary.service.js} +1 -1
  10. package/authentication/server/authentication.api-controller.d.ts +4 -2
  11. package/authentication/server/authentication.api-controller.js +29 -8
  12. package/authentication/server/authentication.service.d.ts +17 -15
  13. package/authentication/server/authentication.service.js +50 -62
  14. package/authentication/server/helper.js +1 -1
  15. package/authentication/server/index.d.ts +1 -3
  16. package/authentication/server/index.js +1 -3
  17. package/authentication/server/module.d.ts +2 -4
  18. package/authentication/server/module.js +3 -7
  19. package/examples/api/custom-authentication.js +14 -5
  20. package/package.json +1 -1
  21. package/authentication/server/authentication-secret-reset.handler.d.ts +0 -4
  22. package/authentication/server/authentication-secret-reset.handler.js +0 -2
  23. package/authentication/server/authentication-subject.resolver.d.ts +0 -7
  24. package/authentication/server/authentication-subject.resolver.js +0 -6
  25. package/authentication/server/authentication-token-payload.provider.d.ts +0 -11
@@ -12,7 +12,7 @@ export type AuthenticationApiDefinition<AdditionalTokenPayload extends Record =
12
12
  export declare const authenticationApiDefinition: {
13
13
  resource: string;
14
14
  endpoints: {
15
- token: {
15
+ getToken: {
16
16
  resource: string;
17
17
  method: "POST";
18
18
  parameters: ObjectSchema<{
@@ -38,6 +38,31 @@ export declare const authenticationApiDefinition: {
38
38
  [dontWaitForValidToken]: boolean;
39
39
  };
40
40
  };
41
+ impersonate: {
42
+ resource: string;
43
+ method: "POST";
44
+ parameters: ObjectSchema<{
45
+ subject: string;
46
+ data: unknown;
47
+ }>;
48
+ result: ObjectSchema<TokenPayloadBase>;
49
+ credentials: true;
50
+ data: {
51
+ [dontWaitForValidToken]: boolean;
52
+ };
53
+ };
54
+ unimpersonate: {
55
+ resource: string;
56
+ method: "POST";
57
+ parameters: ObjectSchema<{
58
+ data: unknown;
59
+ }>;
60
+ result: ObjectSchema<TokenPayloadBase>;
61
+ credentials: true;
62
+ data: {
63
+ [dontWaitForValidToken]: boolean;
64
+ };
65
+ };
41
66
  endSession: {
42
67
  resource: string;
43
68
  method: "POST";
@@ -82,7 +107,7 @@ export declare const authenticationApiDefinition: {
82
107
  export declare function getAuthenticationApiDefinition<AdditionalTokenPayload extends Record, AuthenticationData, AdditionalInitSecretResetData, AdditionalEndpoints>(additionalTokenPayloadSchema: ObjectSchemaOrType<AdditionalTokenPayload>, authenticationDataSchema: SchemaTestable<AuthenticationData>, initSecretResetDataSchema: ObjectSchemaOrType<AdditionalInitSecretResetData>, resource?: string, additionalEndpoints?: AdditionalEndpoints): {
83
108
  resource: string;
84
109
  endpoints: {
85
- token: {
110
+ getToken: {
86
111
  resource: string;
87
112
  method: "POST";
88
113
  parameters: ObjectSchema<{
@@ -108,6 +133,31 @@ export declare function getAuthenticationApiDefinition<AdditionalTokenPayload ex
108
133
  [dontWaitForValidToken]: boolean;
109
134
  };
110
135
  };
136
+ impersonate: {
137
+ resource: string;
138
+ method: "POST";
139
+ parameters: ObjectSchema<{
140
+ subject: string;
141
+ data: AuthenticationData;
142
+ }>;
143
+ result: ObjectSchema<TokenPayload<AdditionalTokenPayload>>;
144
+ credentials: true;
145
+ data: {
146
+ [dontWaitForValidToken]: boolean;
147
+ };
148
+ };
149
+ unimpersonate: {
150
+ resource: string;
151
+ method: "POST";
152
+ parameters: ObjectSchema<{
153
+ data: AuthenticationData;
154
+ }>;
155
+ result: ObjectSchema<TokenPayload<AdditionalTokenPayload>>;
156
+ credentials: true;
157
+ data: {
158
+ [dontWaitForValidToken]: boolean;
159
+ };
160
+ };
111
161
  endSession: {
112
162
  resource: string;
113
163
  method: "POST";
@@ -150,7 +200,7 @@ export declare function getAuthenticationApiDefinition<AdditionalTokenPayload ex
150
200
  };
151
201
  };
152
202
  export declare function getAuthenticationApiEndpointsDefinition<AdditionalTokenPayload extends Record, AuthenticationData, AdditionalInitSecretResetData>(additionalTokenPayloadSchema: ObjectSchemaOrType<AdditionalTokenPayload>, authenticationDataSchema: SchemaTestable<AuthenticationData>, additionalInitSecretResetDataSchema: ObjectSchemaOrType<AdditionalInitSecretResetData>): {
153
- token: {
203
+ getToken: {
154
204
  resource: string;
155
205
  method: "POST";
156
206
  parameters: ObjectSchema<{
@@ -176,6 +226,31 @@ export declare function getAuthenticationApiEndpointsDefinition<AdditionalTokenP
176
226
  [dontWaitForValidToken]: boolean;
177
227
  };
178
228
  };
229
+ impersonate: {
230
+ resource: string;
231
+ method: "POST";
232
+ parameters: ObjectSchema<{
233
+ subject: string;
234
+ data: AuthenticationData;
235
+ }>;
236
+ result: ObjectSchema<TokenPayload<AdditionalTokenPayload>>;
237
+ credentials: true;
238
+ data: {
239
+ [dontWaitForValidToken]: boolean;
240
+ };
241
+ };
242
+ unimpersonate: {
243
+ resource: string;
244
+ method: "POST";
245
+ parameters: ObjectSchema<{
246
+ data: AuthenticationData;
247
+ }>;
248
+ result: ObjectSchema<TokenPayload<AdditionalTokenPayload>>;
249
+ credentials: true;
250
+ data: {
251
+ [dontWaitForValidToken]: boolean;
252
+ };
253
+ };
179
254
  endSession: {
180
255
  resource: string;
181
256
  method: "POST";
@@ -23,7 +23,7 @@ export function getAuthenticationApiDefinition(additionalTokenPayloadSchema, aut
23
23
  export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSchema, authenticationDataSchema, additionalInitSecretResetDataSchema) {
24
24
  const tokenResultSchema = assign(TokenPayloadBase, additionalTokenPayloadSchema);
25
25
  return {
26
- token: {
26
+ getToken: {
27
27
  resource: 'token',
28
28
  method: 'POST',
29
29
  parameters: explicitObject({
@@ -49,6 +49,31 @@ export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSc
49
49
  [dontWaitForValidToken]: true
50
50
  }
51
51
  },
52
+ impersonate: {
53
+ resource: 'impersonate',
54
+ method: 'POST',
55
+ parameters: explicitObject({
56
+ subject: string(),
57
+ data: authenticationDataSchema
58
+ }),
59
+ result: tokenResultSchema,
60
+ credentials: true,
61
+ data: {
62
+ [dontWaitForValidToken]: true
63
+ }
64
+ },
65
+ unimpersonate: {
66
+ resource: 'unimpersonate',
67
+ method: 'POST',
68
+ parameters: explicitObject({
69
+ data: authenticationDataSchema
70
+ }),
71
+ result: tokenResultSchema,
72
+ credentials: true,
73
+ data: {
74
+ [dontWaitForValidToken]: true
75
+ }
76
+ },
52
77
  endSession: {
53
78
  resource: 'end-session',
54
79
  method: 'POST',
@@ -10,7 +10,7 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
10
10
  private readonly tokenUpdateBus;
11
11
  private readonly loggedOutBus;
12
12
  private readonly forceRefreshToken;
13
- private readonly refreshLock;
13
+ private readonly lock;
14
14
  private readonly logger;
15
15
  private readonly disposeToken;
16
16
  readonly error$: import("rxjs").Observable<Error>;
@@ -29,6 +29,8 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
29
29
  readonly loggedOut$: import("rxjs").Observable<void>;
30
30
  private get authenticationData();
31
31
  private set authenticationData(value);
32
+ private get impersonatorAuthenticationData();
33
+ private set impersonatorAuthenticationData(value);
32
34
  get definedToken(): TokenPayload<AdditionalTokenPayload>;
33
35
  get definedSubject(): string;
34
36
  get definedSessionId(): string;
@@ -43,6 +45,8 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
43
45
  logout(): Promise<void>;
44
46
  requestRefresh(data?: AuthenticationData): void;
45
47
  refresh(data?: AuthenticationData): Promise<void>;
48
+ impersonate(subject: string, data?: AuthenticationData): Promise<void>;
49
+ unimpersonate(data?: AuthenticationData): Promise<void>;
46
50
  initResetSecret(subject: string, data: AdditionalInitSecretResetData): Promise<void>;
47
51
  resetSecret(token: string, newSecret: string): Promise<void>;
48
52
  checkSecret(secret: string): Promise<SecretCheckResult>;
@@ -30,6 +30,7 @@ import { assertDefinedPass, isDefined, isNullOrUndefined, isString, isUndefined
30
30
  import { AUTHENTICATION_API_CLIENT, INITIAL_AUTHENTICATION_DATA } from './tokens.js';
31
31
  const tokenStorageKey = 'AuthenticationService:token';
32
32
  const authenticationDataStorageKey = 'AuthenticationService:authentication-data';
33
+ const impersonatorAuthenticationDataStorageKey = 'AuthenticationService:impersonator-authentication-data';
33
34
  const tokenUpdateBusName = 'AuthenticationService:tokenUpdate';
34
35
  const loggedOutBusName = 'AuthenticationService:loggedOut';
35
36
  const refreshLockResource = 'AuthenticationService:refresh';
@@ -39,7 +40,7 @@ let AuthenticationClientService = class AuthenticationClientService {
39
40
  tokenUpdateBus = inject((MessageBus), tokenUpdateBusName);
40
41
  loggedOutBus = inject((MessageBus), loggedOutBusName);
41
42
  forceRefreshToken = new CancellationToken();
42
- refreshLock = inject(Lock, refreshLockResource, { optional: true });
43
+ lock = inject(Lock, refreshLockResource);
43
44
  logger = inject(Logger, 'AuthenticationService');
44
45
  disposeToken = new CancellationToken();
45
46
  error$ = this.errorSubject.asObservable();
@@ -69,6 +70,19 @@ let AuthenticationClientService = class AuthenticationClientService {
69
70
  localStorage.setItem(authenticationDataStorageKey, json);
70
71
  }
71
72
  }
73
+ get impersonatorAuthenticationData() {
74
+ const data = localStorage.getItem(impersonatorAuthenticationDataStorageKey);
75
+ return isNullOrUndefined(data) ? undefined : JSON.parse(data);
76
+ }
77
+ set impersonatorAuthenticationData(data) {
78
+ if (isUndefined(data)) {
79
+ localStorage.removeItem(impersonatorAuthenticationDataStorageKey);
80
+ }
81
+ else {
82
+ const json = JSON.stringify(data);
83
+ localStorage.setItem(impersonatorAuthenticationDataStorageKey, json);
84
+ }
85
+ }
72
86
  get definedToken() {
73
87
  return assertDefinedPass(this.token(), 'No token available.');
74
88
  }
@@ -110,7 +124,7 @@ let AuthenticationClientService = class AuthenticationClientService {
110
124
  if (isDefined(data)) {
111
125
  this.setAdditionalData(data);
112
126
  }
113
- const token = await this.client.token({ subject, secret, data: this.authenticationData });
127
+ const token = await this.client.getToken({ subject, secret, data: this.authenticationData });
114
128
  this.setNewToken(token);
115
129
  }
116
130
  async logout() {
@@ -144,6 +158,35 @@ let AuthenticationClientService = class AuthenticationClientService {
144
158
  throw error;
145
159
  }
146
160
  }
161
+ async impersonate(subject, data) {
162
+ await this.lock.use(10000, true, async () => {
163
+ this.impersonatorAuthenticationData = this.authenticationData;
164
+ this.authenticationData = data;
165
+ try {
166
+ const token = await this.client.impersonate({ subject, data: data });
167
+ this.setNewToken(token);
168
+ }
169
+ catch (error) {
170
+ await this.handleRefreshError(error);
171
+ throw error;
172
+ }
173
+ });
174
+ }
175
+ async unimpersonate(data) {
176
+ await this.lock.use(10000, true, async () => {
177
+ const newData = data ?? this.impersonatorAuthenticationData;
178
+ try {
179
+ const token = await this.client.unimpersonate({ data: newData });
180
+ this.authenticationData = newData;
181
+ this.impersonatorAuthenticationData = undefined;
182
+ this.setNewToken(token);
183
+ }
184
+ catch (error) {
185
+ await this.handleRefreshError(error);
186
+ throw error;
187
+ }
188
+ });
189
+ }
147
190
  async initResetSecret(subject, data) {
148
191
  await this.client.initSecretReset({ subject, data });
149
192
  }
@@ -180,12 +223,7 @@ let AuthenticationClientService = class AuthenticationClientService {
180
223
  async refreshLoop() {
181
224
  while (this.disposeToken.isUnset) {
182
225
  try {
183
- if (isDefined(this.refreshLock)) {
184
- await this.refreshLock.use(0, false, async () => this.refreshLoopIteration());
185
- }
186
- else {
187
- await this.refreshLoopIteration();
188
- }
226
+ await this.lock.use(0, false, async () => this.refreshLoopIteration());
189
227
  await firstValueFrom(race([timer(2500), this.disposeToken, this.forceRefreshToken]));
190
228
  }
191
229
  catch {
@@ -9,4 +9,5 @@ export declare class TokenPayloadBase {
9
9
  refreshTokenExp: number;
10
10
  sessionId: string;
11
11
  subject: string;
12
+ impersonator?: string;
12
13
  }
@@ -19,6 +19,7 @@ export class TokenPayloadBase {
19
19
  refreshTokenExp;
20
20
  sessionId;
21
21
  subject;
22
+ impersonator;
22
23
  }
23
24
  __decorate([
24
25
  Property(),
@@ -44,3 +45,7 @@ __decorate([
44
45
  Property(),
45
46
  __metadata("design:type", String)
46
47
  ], TokenPayloadBase.prototype, "subject", void 0);
48
+ __decorate([
49
+ Property({ optional: true }),
50
+ __metadata("design:type", String)
51
+ ], TokenPayloadBase.prototype, "impersonator", void 0);
@@ -10,6 +10,7 @@ export type RefreshToken = JwtToken<{
10
10
  /** expiration timestamp in seconds */
11
11
  exp: number;
12
12
  subject: string;
13
+ impersonator?: string;
13
14
  sessionId: string;
14
15
  secret: string;
15
16
  }>;
@@ -0,0 +1,25 @@
1
+ import type { Record } from '../../types.js';
2
+ import type { TokenPayload } from '../index.js';
3
+ import type { InitSecretResetData } from '../models/init-secret-reset-data.model.js';
4
+ export declare enum GetTokenPayloadContextAction {
5
+ GetToken = 0,
6
+ Refresh = 1
7
+ }
8
+ export type GetTokenPayloadContext = {
9
+ action: GetTokenPayloadContextAction;
10
+ };
11
+ export declare abstract class AuthenticationAncillaryService<AdditionalTokenPayload extends Record = Record<never>, AuthenticationData = void, AdditionalInitSecretResetData extends Record = Record<never>> {
12
+ /**
13
+ * Resolve a provided subject to the actual subject used for authentication.
14
+ * Useful for example if you want to be able to login via mail but actual subject is the user id.
15
+ */
16
+ abstract resolveSubject(providedSubject: string): string | Promise<string>;
17
+ abstract getTokenPayload(subject: string, authenticationData: AuthenticationData, context: GetTokenPayloadContext): AdditionalTokenPayload | Promise<AdditionalTokenPayload>;
18
+ abstract handleInitSecretReset(data: InitSecretResetData & AdditionalInitSecretResetData): void | Promise<void>;
19
+ /**
20
+ * Check if token is allowed to impersonate subject
21
+ * @param token Token which tries to impersonate
22
+ * @param subject Subject to impersonate
23
+ */
24
+ abstract canImpersonate(token: TokenPayload<AdditionalTokenPayload>, subject: string, authenticationData: AuthenticationData): boolean | Promise<boolean>;
25
+ }
@@ -3,5 +3,5 @@ export var GetTokenPayloadContextAction;
3
3
  GetTokenPayloadContextAction[GetTokenPayloadContextAction["GetToken"] = 0] = "GetToken";
4
4
  GetTokenPayloadContextAction[GetTokenPayloadContextAction["Refresh"] = 1] = "Refresh";
5
5
  })(GetTokenPayloadContextAction || (GetTokenPayloadContextAction = {}));
6
- export class AuthenticationTokenPayloadProvider {
6
+ export class AuthenticationAncillaryService {
7
7
  }
@@ -8,14 +8,16 @@ import { AuthenticationService } from './authentication.service.js';
8
8
  export declare class AuthenticationApiController<AdditionalTokenPayload extends Record, AuthenticationData, AdditionalInitSecretResetData extends Record> implements ApiController<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>> {
9
9
  readonly authenticationService: AuthenticationService<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>;
10
10
  constructor(authenticationService: AuthenticationService<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>);
11
- token({ parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'token'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'token'>>;
11
+ getToken({ parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'getToken'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'getToken'>>;
12
12
  refresh({ request, parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'refresh'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'refresh'>>;
13
+ impersonate({ request, parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'impersonate'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'impersonate'>>;
14
+ unimpersonate({ request, parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'unimpersonate'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'unimpersonate'>>;
13
15
  endSession({ request }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'endSession'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'endSession'>>;
14
16
  initSecretReset({ parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'initSecretReset'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'initSecretReset'>>;
15
17
  resetSecret({ parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'resetSecret'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'resetSecret'>>;
16
18
  checkSecret({ parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'checkSecret'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'checkSecret'>>;
17
19
  timestamp(): ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'timestamp'>;
18
- protected getTokenResponse({ token, jsonToken, refreshToken }: TokenResult<AdditionalTokenPayload>): HttpServerResponse;
20
+ protected getTokenResponse({ token, jsonToken, refreshToken, omitImpersonatorRefreshToken, impersonatorRefreshToken, impersonatorRefreshTokenExpiration }: TokenResult<AdditionalTokenPayload>): HttpServerResponse;
19
21
  }
20
22
  export declare function getAuthenticationApiController<AdditionalTokenPayload extends Record, AuthenticationData, AdditionalInitSecretResetData extends Record>(// eslint-disable-line @typescript-eslint/explicit-function-return-type
21
23
  additionalTokenPayloadSchema: ObjectSchemaOrType<AdditionalTokenPayload>, authenticationDataSchema: SchemaTestable<AuthenticationData>, additionalInitSecretResetData: ObjectSchemaOrType<AdditionalInitSecretResetData>): Type<AuthenticationApiController<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>>;
@@ -11,16 +11,18 @@ import { apiController } from '../../api/server/index.js';
11
11
  import { InvalidCredentialsError } from '../../errors/invalid-credentials.error.js';
12
12
  import { HttpServerResponse } from '../../http/server/index.js';
13
13
  import { currentTimestamp } from '../../utils/date-time.js';
14
+ import { assertDefinedPass, isDefined } from '../../utils/type-guards.js';
14
15
  import { authenticationApiDefinition, getAuthenticationApiDefinition } from '../authentication.api.js';
15
16
  import { AuthenticationService } from './authentication.service.js';
16
17
  import { tryGetAuthorizationTokenStringFromRequest } from './helper.js';
17
18
  const cookieBaseOptions = { path: '/', httpOnly: true, secure: true, sameSite: 'strict' };
19
+ const deleteCookie = { value: '', ...cookieBaseOptions, expires: -1 };
18
20
  let AuthenticationApiController = class AuthenticationApiController {
19
21
  authenticationService;
20
22
  constructor(authenticationService) {
21
23
  this.authenticationService = authenticationService;
22
24
  }
23
- async token({ parameters }) {
25
+ async getToken({ parameters }) {
24
26
  const authenticationResult = await this.authenticationService.authenticate(parameters.subject, parameters.secret);
25
27
  if (!authenticationResult.success) {
26
28
  throw new InvalidCredentialsError();
@@ -29,8 +31,19 @@ let AuthenticationApiController = class AuthenticationApiController {
29
31
  return this.getTokenResponse(result);
30
32
  }
31
33
  async refresh({ request, parameters }) {
32
- const tokenString = tryGetAuthorizationTokenStringFromRequest(request, 'refreshToken') ?? '';
33
- const result = await this.authenticationService.refresh(tokenString, parameters.data);
34
+ const refreshTokenString = tryGetAuthorizationTokenStringFromRequest(request, 'refreshToken') ?? '';
35
+ const result = await this.authenticationService.refresh(refreshTokenString, parameters.data);
36
+ return this.getTokenResponse(result);
37
+ }
38
+ async impersonate({ request, parameters }) {
39
+ const tokenString = tryGetAuthorizationTokenStringFromRequest(request) ?? '';
40
+ const refreshTokenString = tryGetAuthorizationTokenStringFromRequest(request, 'refreshToken') ?? '';
41
+ const impersonatorResult = await this.authenticationService.impersonate(tokenString, refreshTokenString, parameters.subject, parameters.data);
42
+ return this.getTokenResponse(impersonatorResult);
43
+ }
44
+ async unimpersonate({ request, parameters }) {
45
+ const impersonatorRefreshTokenString = tryGetAuthorizationTokenStringFromRequest(request, 'impersonatorRefreshToken') ?? '';
46
+ const result = await this.authenticationService.refresh(impersonatorRefreshTokenString, parameters.data, { omitImpersonator: true });
34
47
  return this.getTokenResponse(result);
35
48
  }
36
49
  async endSession({ request }) {
@@ -54,8 +67,9 @@ let AuthenticationApiController = class AuthenticationApiController {
54
67
  const result = 'ok';
55
68
  return new HttpServerResponse({
56
69
  cookies: {
57
- authorization: { value: '', ...cookieBaseOptions, expires: -1 },
58
- refreshToken: { value: '', ...cookieBaseOptions, expires: -1 }
70
+ authorization: deleteCookie,
71
+ refreshToken: deleteCookie,
72
+ impersonatorRefreshToken: deleteCookie
59
73
  },
60
74
  body: {
61
75
  json: result
@@ -76,9 +90,9 @@ let AuthenticationApiController = class AuthenticationApiController {
76
90
  timestamp() {
77
91
  return currentTimestamp();
78
92
  }
79
- getTokenResponse({ token, jsonToken, refreshToken }) {
93
+ getTokenResponse({ token, jsonToken, refreshToken, omitImpersonatorRefreshToken, impersonatorRefreshToken, impersonatorRefreshTokenExpiration }) {
80
94
  const result = jsonToken.payload;
81
- return new HttpServerResponse({
95
+ const options = {
82
96
  cookies: {
83
97
  authorization: { value: `Bearer ${token}`, ...cookieBaseOptions, expires: jsonToken.payload.exp * 1000 },
84
98
  refreshToken: { value: `Bearer ${refreshToken}`, ...cookieBaseOptions, expires: jsonToken.payload.refreshTokenExp * 1000 }
@@ -86,7 +100,14 @@ let AuthenticationApiController = class AuthenticationApiController {
86
100
  body: {
87
101
  json: result
88
102
  }
89
- });
103
+ };
104
+ if (isDefined(impersonatorRefreshToken)) {
105
+ options.cookies['impersonatorRefreshToken'] = { value: `Bearer ${refreshToken}`, ...cookieBaseOptions, expires: assertDefinedPass(impersonatorRefreshTokenExpiration) * 1000 };
106
+ }
107
+ if (omitImpersonatorRefreshToken == true) {
108
+ options.cookies['impersonatorRefreshToken'] = deleteCookie;
109
+ }
110
+ return new HttpServerResponse(options);
90
111
  }
91
112
  };
92
113
  AuthenticationApiController = __decorate([
@@ -2,13 +2,7 @@ import type { AfterResolve } from '../../injector/index.js';
2
2
  import { afterResolve } from '../../injector/index.js';
3
3
  import type { Record } from '../../types.js';
4
4
  import type { RefreshToken, SecretCheckResult, SecretResetToken, Token } from '../models/index.js';
5
- import { AuthenticationCredentialsRepository } from './authentication-credentials.repository.js';
6
5
  import type { SecretTestResult } from './authentication-secret-requirements.validator.js';
7
- import { AuthenticationSecretRequirementsValidator } from './authentication-secret-requirements.validator.js';
8
- import { AuthenticationSecretResetHandler } from './authentication-secret-reset.handler.js';
9
- import { AuthenticationSessionRepository } from './authentication-session.repository.js';
10
- import { AuthenticationSubjectResolver } from './authentication-subject.resolver.js';
11
- import { AuthenticationTokenPayloadProvider } from './authentication-token-payload.provider.js';
12
6
  export type CreateTokenData<AdditionalTokenPayload extends Record> = {
13
7
  tokenVersion?: number;
14
8
  jwtId?: string;
@@ -17,6 +11,7 @@ export type CreateTokenData<AdditionalTokenPayload extends Record> = {
17
11
  additionalTokenPayload: AdditionalTokenPayload;
18
12
  subject: string;
19
13
  sessionId: string;
14
+ impersonator: string | undefined;
20
15
  refreshTokenExpiration: number;
21
16
  timestamp?: number;
22
17
  };
@@ -50,6 +45,9 @@ export type TokenResult<AdditionalTokenPayload extends Record> = {
50
45
  token: string;
51
46
  jsonToken: Token<AdditionalTokenPayload>;
52
47
  refreshToken: string;
48
+ omitImpersonatorRefreshToken?: boolean;
49
+ impersonatorRefreshToken?: string;
50
+ impersonatorRefreshTokenExpiration?: number;
53
51
  };
54
52
  export type SetCredentialsOptions = {
55
53
  /** skip validation for password strength */
@@ -69,11 +67,8 @@ export declare class AuthenticationService<AdditionalTokenPayload extends Record
69
67
  private readonly credentialsRepository;
70
68
  private readonly sessionRepository;
71
69
  private readonly authenticationSecretRequirementsValidator;
72
- private readonly tokenPayloadProvider;
73
- private readonly subjectResolver;
74
- private readonly authenticationResetSecretHandler;
70
+ private readonly authenticationAncillaryService;
75
71
  private readonly options;
76
- private readonly secret;
77
72
  private readonly tokenVersion;
78
73
  private readonly tokenTimeToLive;
79
74
  private readonly refreshTokenTimeToLive;
@@ -81,14 +76,19 @@ export declare class AuthenticationService<AdditionalTokenPayload extends Record
81
76
  private derivedTokenSigningSecret;
82
77
  private derivedRefreshTokenSigningSecret;
83
78
  private derivedSecretResetTokenSigningSecret;
84
- constructor(credentialsRepository: AuthenticationCredentialsRepository, sessionRepository: AuthenticationSessionRepository, authenticationSecretRequirementsValidator: AuthenticationSecretRequirementsValidator, subjectResolver: AuthenticationSubjectResolver | undefined, tokenPayloadProvider: AuthenticationTokenPayloadProvider<AdditionalTokenPayload, AuthenticationData> | undefined, authenticationResetSecretHandler: AuthenticationSecretResetHandler<AdditionalInitSecretResetData> | undefined, options: AuthenticationServiceOptions);
85
79
  [afterResolve](): Promise<void>;
86
80
  initialize(): Promise<void>;
87
81
  setCredentials(subject: string, secret: string, options?: SetCredentialsOptions): Promise<void>;
88
82
  authenticate(subject: string, secret: string): Promise<AuthenticationResult>;
89
- getToken(subject: string, authenticationData: AuthenticationData): Promise<TokenResult<AdditionalTokenPayload>>;
83
+ getToken(subject: string, authenticationData: AuthenticationData, { impersonator }?: {
84
+ impersonator?: string;
85
+ }): Promise<TokenResult<AdditionalTokenPayload>>;
90
86
  endSession(sessionId: string): Promise<void>;
91
- refresh(refreshToken: string, authenticationData: AuthenticationData): Promise<TokenResult<AdditionalTokenPayload>>;
87
+ refresh(refreshToken: string, authenticationData: AuthenticationData, { omitImpersonator }?: {
88
+ omitImpersonator?: boolean;
89
+ }): Promise<TokenResult<AdditionalTokenPayload>>;
90
+ impersonate(impersonatorRoken: string, impersonatorRefreshToken: string, subject: string, authenticationData: AuthenticationData): Promise<TokenResult<AdditionalTokenPayload>>;
91
+ unimpersonate(impersonatorRefreshToken: string, authenticationData: AuthenticationData): Promise<TokenResult<AdditionalTokenPayload>>;
92
92
  initSecretReset(subject: string, data: AdditionalInitSecretResetData): Promise<void>;
93
93
  resetSecret(tokenString: string, newSecret: string): Promise<void>;
94
94
  checkSecret(secret: string): Promise<SecretCheckResult>;
@@ -99,9 +99,11 @@ export declare class AuthenticationService<AdditionalTokenPayload extends Record
99
99
  validateSecretResetToken(token: string): Promise<SecretResetToken>;
100
100
  resolveSubject(subject: string): Promise<string>;
101
101
  /** Creates a token without session or refresh token and is not saved in database */
102
- createToken({ tokenVersion, jwtId, issuedAt, expiration, additionalTokenPayload, subject, sessionId, refreshTokenExpiration, timestamp }: CreateTokenData<AdditionalTokenPayload>): Promise<CreateTokenResult<AdditionalTokenPayload>>;
102
+ createToken({ tokenVersion, jwtId, issuedAt, expiration, additionalTokenPayload, subject, sessionId, refreshTokenExpiration, impersonator: impersonatedBy, timestamp }: CreateTokenData<AdditionalTokenPayload>): Promise<CreateTokenResult<AdditionalTokenPayload>>;
103
103
  /** Creates a refresh token without session or something else. */
104
- createRefreshToken(subject: string, sessionId: string, expirationTimestamp: number): Promise<CreateRefreshTokenResult>;
104
+ createRefreshToken(subject: string, sessionId: string, expirationTimestamp: number, options?: {
105
+ impersonator?: string;
106
+ }): Promise<CreateRefreshTokenResult>;
105
107
  private createSecretResetToken;
106
108
  private deriveSigningSecrets;
107
109
  private getHash;
@@ -4,15 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- var __param = (this && this.__param) || function (paramIndex, decorator) {
11
- return function (target, key) { decorator(target, key, paramIndex); }
12
- };
7
+ import { ForbiddenError } from '../../errors/forbidden.error.js';
13
8
  import { InvalidTokenError } from '../../errors/invalid-token.error.js';
14
9
  import { NotImplementedError } from '../../errors/not-implemented.error.js';
15
- import { Inject, Optional, Singleton, afterResolve } from '../../injector/index.js';
10
+ import { Singleton, afterResolve, inject } from '../../injector/index.js';
16
11
  import { Alphabet } from '../../utils/alphabet.js';
17
12
  import { deriveBytesMultiple, importPbkdf2Key } from '../../utils/cryptography.js';
18
13
  import { currentTimestamp, timestampToTimestampSeconds } from '../../utils/date-time.js';
@@ -21,12 +16,10 @@ import { createJwtTokenString } from '../../utils/jwt.js';
21
16
  import { getRandomBytes, getRandomString } from '../../utils/random.js';
22
17
  import { isBinaryData, isString, isUndefined } from '../../utils/type-guards.js';
23
18
  import { millisecondsPerDay, millisecondsPerMinute } from '../../utils/units.js';
19
+ import { AuthenticationAncillaryService, GetTokenPayloadContextAction } from './authentication-ancillary.service.js';
24
20
  import { AuthenticationCredentialsRepository } from './authentication-credentials.repository.js';
25
21
  import { AuthenticationSecretRequirementsValidator } from './authentication-secret-requirements.validator.js';
26
- import { AuthenticationSecretResetHandler } from './authentication-secret-reset.handler.js';
27
22
  import { AuthenticationSessionRepository } from './authentication-session.repository.js';
28
- import { AuthenticationSubjectResolver } from './authentication-subject.resolver.js';
29
- import { AuthenticationTokenPayloadProvider, GetTokenPayloadContextAction } from './authentication-token-payload.provider.js';
30
23
  import { getRefreshTokenFromString, getSecretResetTokenFromString, getTokenFromString } from './helper.js';
31
24
  export class AuthenticationServiceOptions {
32
25
  /**
@@ -45,34 +38,18 @@ export class AuthenticationServiceOptions {
45
38
  }
46
39
  const SIGNING_SECRETS_LENGTH = 64;
47
40
  let AuthenticationService = class AuthenticationService {
48
- credentialsRepository;
49
- sessionRepository;
50
- authenticationSecretRequirementsValidator;
51
- tokenPayloadProvider;
52
- subjectResolver;
53
- authenticationResetSecretHandler;
54
- options;
55
- secret;
56
- tokenVersion;
57
- tokenTimeToLive;
58
- refreshTokenTimeToLive;
59
- secretResetTokenTimeToLive;
41
+ credentialsRepository = inject(AuthenticationCredentialsRepository);
42
+ sessionRepository = inject(AuthenticationSessionRepository);
43
+ authenticationSecretRequirementsValidator = inject(AuthenticationSecretRequirementsValidator);
44
+ authenticationAncillaryService = inject(AuthenticationAncillaryService, undefined, { optional: true });
45
+ options = inject(AuthenticationServiceOptions);
46
+ tokenVersion = this.options.version ?? 1;
47
+ tokenTimeToLive = this.options.tokenTimeToLive ?? (5 * millisecondsPerMinute);
48
+ refreshTokenTimeToLive = this.options.refreshTokenTimeToLive ?? (5 * millisecondsPerDay);
49
+ secretResetTokenTimeToLive = this.options.secretResetTokenTimeToLive ?? (10 * millisecondsPerMinute);
60
50
  derivedTokenSigningSecret;
61
51
  derivedRefreshTokenSigningSecret;
62
52
  derivedSecretResetTokenSigningSecret;
63
- constructor(credentialsRepository, sessionRepository, authenticationSecretRequirementsValidator, subjectResolver, tokenPayloadProvider, authenticationResetSecretHandler, options) {
64
- this.credentialsRepository = credentialsRepository;
65
- this.sessionRepository = sessionRepository;
66
- this.authenticationSecretRequirementsValidator = authenticationSecretRequirementsValidator;
67
- this.subjectResolver = subjectResolver;
68
- this.tokenPayloadProvider = tokenPayloadProvider;
69
- this.authenticationResetSecretHandler = authenticationResetSecretHandler;
70
- this.options = options;
71
- this.tokenVersion = options.version ?? 1;
72
- this.tokenTimeToLive = options.tokenTimeToLive ?? (5 * millisecondsPerMinute);
73
- this.refreshTokenTimeToLive = options.refreshTokenTimeToLive ?? (5 * millisecondsPerDay);
74
- this.secretResetTokenTimeToLive = options.secretResetTokenTimeToLive ?? (10 * millisecondsPerMinute);
75
- }
76
53
  async [afterResolve]() {
77
54
  await this.initialize();
78
55
  }
@@ -114,7 +91,7 @@ let AuthenticationService = class AuthenticationService {
114
91
  }
115
92
  return { success: false };
116
93
  }
117
- async getToken(subject, authenticationData) {
94
+ async getToken(subject, authenticationData, { impersonator } = {}) {
118
95
  const actualSubject = await this.resolveSubject(subject);
119
96
  const now = currentTimestamp();
120
97
  const end = now + this.refreshTokenTimeToLive;
@@ -126,9 +103,9 @@ let AuthenticationService = class AuthenticationService {
126
103
  refreshTokenSalt: new Uint8Array(),
127
104
  refreshTokenHash: new Uint8Array()
128
105
  });
129
- const tokenPayload = await this.tokenPayloadProvider?.getTokenPayload(actualSubject, authenticationData, { action: GetTokenPayloadContextAction.GetToken });
130
- const { token, jsonToken } = await this.createToken({ additionalTokenPayload: tokenPayload, subject: actualSubject, sessionId: session.id, refreshTokenExpiration: end, timestamp: now });
131
- const refreshToken = await this.createRefreshToken(actualSubject, session.id, end);
106
+ const tokenPayload = await this.authenticationAncillaryService?.getTokenPayload(actualSubject, authenticationData, { action: GetTokenPayloadContextAction.GetToken });
107
+ const { token, jsonToken } = await this.createToken({ additionalTokenPayload: tokenPayload, subject: actualSubject, impersonator, sessionId: session.id, refreshTokenExpiration: end, timestamp: now });
108
+ const refreshToken = await this.createRefreshToken(actualSubject, session.id, end, { impersonator });
132
109
  await this.sessionRepository.extend(session.id, {
133
110
  end,
134
111
  refreshTokenHashVersion: 1,
@@ -141,11 +118,11 @@ let AuthenticationService = class AuthenticationService {
141
118
  const now = currentTimestamp();
142
119
  await this.sessionRepository.end(sessionId, now);
143
120
  }
144
- async refresh(refreshToken, authenticationData) {
145
- const validatedToken = await this.validateRefreshToken(refreshToken);
146
- const sessionId = validatedToken.payload.sessionId;
121
+ async refresh(refreshToken, authenticationData, { omitImpersonator = false } = {}) {
122
+ const validatedRefreshToken = await this.validateRefreshToken(refreshToken);
123
+ const sessionId = validatedRefreshToken.payload.sessionId;
147
124
  const session = await this.sessionRepository.load(sessionId);
148
- const hash = await this.getHash(validatedToken.payload.secret, session.refreshTokenSalt);
125
+ const hash = await this.getHash(validatedRefreshToken.payload.secret, session.refreshTokenSalt);
149
126
  if (session.end <= currentTimestamp()) {
150
127
  throw new InvalidTokenError('Session is expired.');
151
128
  }
@@ -153,20 +130,38 @@ let AuthenticationService = class AuthenticationService {
153
130
  throw new InvalidTokenError('Invalid refresh token.');
154
131
  }
155
132
  const now = currentTimestamp();
133
+ const impersonator = omitImpersonator ? undefined : validatedRefreshToken.payload.impersonator;
156
134
  const newEnd = now + this.refreshTokenTimeToLive;
157
- const tokenPayload = await this.tokenPayloadProvider?.getTokenPayload(session.subject, authenticationData, { action: GetTokenPayloadContextAction.Refresh });
158
- const { token, jsonToken } = await this.createToken({ additionalTokenPayload: tokenPayload, subject: session.subject, sessionId, refreshTokenExpiration: newEnd, timestamp: now });
159
- const newRefreshToken = await this.createRefreshToken(validatedToken.payload.subject, sessionId, newEnd);
135
+ const tokenPayload = await this.authenticationAncillaryService?.getTokenPayload(session.subject, authenticationData, { action: GetTokenPayloadContextAction.Refresh });
136
+ const { token, jsonToken } = await this.createToken({ additionalTokenPayload: tokenPayload, subject: session.subject, sessionId, refreshTokenExpiration: newEnd, impersonator, timestamp: now });
137
+ const newRefreshToken = await this.createRefreshToken(validatedRefreshToken.payload.subject, sessionId, newEnd, { impersonator });
160
138
  await this.sessionRepository.extend(sessionId, {
161
139
  end: newEnd,
162
140
  refreshTokenHashVersion: 1,
163
141
  refreshTokenSalt: newRefreshToken.salt,
164
142
  refreshTokenHash: newRefreshToken.hash
165
143
  });
166
- return { token, jsonToken, refreshToken: newRefreshToken.token };
144
+ return { token, jsonToken, refreshToken: newRefreshToken.token, omitImpersonatorRefreshToken: omitImpersonator };
145
+ }
146
+ async impersonate(impersonatorRoken, impersonatorRefreshToken, subject, authenticationData) {
147
+ const validatedImpersonatorRoken = await this.validateToken(impersonatorRoken);
148
+ const validatedImpersonatorRefreshToken = await this.validateRefreshToken(impersonatorRefreshToken);
149
+ const allowed = await this.authenticationAncillaryService?.canImpersonate(validatedImpersonatorRoken.payload, subject, authenticationData) ?? false;
150
+ if (!allowed) {
151
+ throw new ForbiddenError('Impersonation forbidden.');
152
+ }
153
+ const tokenResult = await this.getToken(subject, authenticationData, { impersonator: validatedImpersonatorRoken.payload.subject });
154
+ return {
155
+ ...tokenResult,
156
+ impersonatorRefreshToken,
157
+ impersonatorRefreshTokenExpiration: validatedImpersonatorRefreshToken.payload.exp
158
+ };
159
+ }
160
+ async unimpersonate(impersonatorRefreshToken, authenticationData) {
161
+ return this.refresh(impersonatorRefreshToken, authenticationData, { omitImpersonator: true });
167
162
  }
168
163
  async initSecretReset(subject, data) {
169
- if (isUndefined(this.authenticationResetSecretHandler)) {
164
+ if (isUndefined(this.authenticationAncillaryService)) {
170
165
  throw new NotImplementedError();
171
166
  }
172
167
  const actualSubject = await this.resolveSubject(subject);
@@ -176,7 +171,7 @@ let AuthenticationService = class AuthenticationService {
176
171
  token: secretResetToken.token,
177
172
  ...data
178
173
  };
179
- await this.authenticationResetSecretHandler.handleInitSecretReset(initSecretResetData);
174
+ await this.authenticationAncillaryService.handleInitSecretReset(initSecretResetData);
180
175
  }
181
176
  async resetSecret(tokenString, newSecret) {
182
177
  const token = await this.validateSecretResetToken(tokenString);
@@ -201,10 +196,10 @@ let AuthenticationService = class AuthenticationService {
201
196
  return getSecretResetTokenFromString(token, this.derivedSecretResetTokenSigningSecret);
202
197
  }
203
198
  async resolveSubject(subject) {
204
- return this.subjectResolver?.resolveSubject(subject) ?? subject;
199
+ return this.authenticationAncillaryService?.resolveSubject(subject) ?? subject;
205
200
  }
206
201
  /** Creates a token without session or refresh token and is not saved in database */
207
- async createToken({ tokenVersion, jwtId, issuedAt, expiration, additionalTokenPayload, subject, sessionId, refreshTokenExpiration, timestamp = currentTimestamp() }) {
202
+ async createToken({ tokenVersion, jwtId, issuedAt, expiration, additionalTokenPayload, subject, sessionId, refreshTokenExpiration, impersonator: impersonatedBy, timestamp = currentTimestamp() }) {
208
203
  const header = {
209
204
  v: tokenVersion ?? this.tokenVersion,
210
205
  alg: 'HS256',
@@ -217,6 +212,7 @@ let AuthenticationService = class AuthenticationService {
217
212
  refreshTokenExp: timestampToTimestampSeconds(refreshTokenExpiration),
218
213
  sessionId,
219
214
  subject,
215
+ impersonator: impersonatedBy,
220
216
  ...additionalTokenPayload
221
217
  };
222
218
  const jsonToken = {
@@ -227,7 +223,7 @@ let AuthenticationService = class AuthenticationService {
227
223
  return { token, jsonToken };
228
224
  }
229
225
  /** Creates a refresh token without session or something else. */
230
- async createRefreshToken(subject, sessionId, expirationTimestamp) {
226
+ async createRefreshToken(subject, sessionId, expirationTimestamp, options) {
231
227
  const secret = getRandomString(64, Alphabet.LowerUpperCaseNumbers);
232
228
  const salt = getRandomBytes(32);
233
229
  const hash = await this.getHash(secret, salt);
@@ -239,6 +235,7 @@ let AuthenticationService = class AuthenticationService {
239
235
  payload: {
240
236
  exp: timestampToTimestampSeconds(expirationTimestamp),
241
237
  subject,
238
+ impersonator: options?.impersonator,
242
239
  sessionId,
243
240
  secret
244
241
  }
@@ -275,15 +272,6 @@ let AuthenticationService = class AuthenticationService {
275
272
  }
276
273
  };
277
274
  AuthenticationService = __decorate([
278
- Singleton(),
279
- __param(3, Inject(AuthenticationSubjectResolver)),
280
- __param(3, Optional()),
281
- __param(4, Inject(AuthenticationTokenPayloadProvider)),
282
- __param(4, Optional()),
283
- __param(5, Inject(AuthenticationSecretResetHandler)),
284
- __param(5, Optional()),
285
- __metadata("design:paramtypes", [AuthenticationCredentialsRepository,
286
- AuthenticationSessionRepository,
287
- AuthenticationSecretRequirementsValidator, Object, Object, Object, AuthenticationServiceOptions])
275
+ Singleton()
288
276
  ], AuthenticationService);
289
277
  export { AuthenticationService };
@@ -46,7 +46,7 @@ export async function getTokenFromString(tokenString, tokenVersion, secret) {
46
46
  if (validatedToken.header.v != tokenVersion) {
47
47
  throw new InvalidTokenError('Invalid token version');
48
48
  }
49
- if ((validatedToken.payload.exp + 2500) <= currentTimestampSeconds()) {
49
+ if (validatedToken.payload.exp <= currentTimestampSeconds()) {
50
50
  throw new InvalidTokenError('Token expired');
51
51
  }
52
52
  return validatedToken;
@@ -1,10 +1,8 @@
1
+ export * from './authentication-ancillary.service.js';
1
2
  export * from './authentication-api-request-token.provider.js';
2
3
  export * from './authentication-credentials.repository.js';
3
4
  export * from './authentication-secret-requirements.validator.js';
4
- export * from './authentication-secret-reset.handler.js';
5
5
  export * from './authentication-session.repository.js';
6
- export * from './authentication-subject.resolver.js';
7
- export * from './authentication-token-payload.provider.js';
8
6
  export * from './authentication.api-controller.js';
9
7
  export * from './authentication.service.js';
10
8
  export * from './helper.js';
@@ -1,10 +1,8 @@
1
+ export * from './authentication-ancillary.service.js';
1
2
  export * from './authentication-api-request-token.provider.js';
2
3
  export * from './authentication-credentials.repository.js';
3
4
  export * from './authentication-secret-requirements.validator.js';
4
- export * from './authentication-secret-reset.handler.js';
5
5
  export * from './authentication-session.repository.js';
6
- export * from './authentication-subject.resolver.js';
7
- export * from './authentication-token-payload.provider.js';
8
6
  export * from './authentication.api-controller.js';
9
7
  export * from './authentication.service.js';
10
8
  export * from './helper.js';
@@ -1,9 +1,8 @@
1
1
  import type { Provider } from '../../injector/provider.js';
2
2
  import type { InjectionToken } from '../../injector/token.js';
3
+ import { AuthenticationAncillaryService } from './authentication-ancillary.service.js';
3
4
  import { AuthenticationCredentialsRepository } from './authentication-credentials.repository.js';
4
5
  import { AuthenticationSessionRepository } from './authentication-session.repository.js';
5
- import { AuthenticationSubjectResolver } from './authentication-subject.resolver.js';
6
- import { AuthenticationTokenPayloadProvider } from './authentication-token-payload.provider.js';
7
6
  import { AuthenticationService, AuthenticationServiceOptions } from './authentication.service.js';
8
7
  export type AuthenticationModuleConfig = {
9
8
  serviceOptions?: AuthenticationServiceOptions | Provider<AuthenticationServiceOptions>;
@@ -11,7 +10,6 @@ export type AuthenticationModuleConfig = {
11
10
  sessionRepository: InjectionToken<AuthenticationSessionRepository>;
12
11
  /** override default AuthenticationService */
13
12
  authenticationService?: InjectionToken<AuthenticationService<any, any, any>>;
14
- tokenPayloadProvider?: InjectionToken<AuthenticationTokenPayloadProvider<any, any>>;
15
- subjectResolver?: InjectionToken<AuthenticationSubjectResolver>;
13
+ authenticationAncillaryService?: InjectionToken<AuthenticationAncillaryService<any, any, any>>;
16
14
  };
17
15
  export declare function configureAuthenticationServer(config: AuthenticationModuleConfig): void;
@@ -1,10 +1,9 @@
1
1
  import { Injector } from '../../injector/injector.js';
2
2
  import { isProvider } from '../../injector/provider.js';
3
3
  import { isDefined } from '../../utils/type-guards.js';
4
+ import { AuthenticationAncillaryService } from './authentication-ancillary.service.js';
4
5
  import { AuthenticationCredentialsRepository } from './authentication-credentials.repository.js';
5
6
  import { AuthenticationSessionRepository } from './authentication-session.repository.js';
6
- import { AuthenticationSubjectResolver } from './authentication-subject.resolver.js';
7
- import { AuthenticationTokenPayloadProvider } from './authentication-token-payload.provider.js';
8
7
  import { AuthenticationService, AuthenticationServiceOptions } from './authentication.service.js';
9
8
  export function configureAuthenticationServer(config) {
10
9
  if (isDefined(config.serviceOptions)) {
@@ -18,10 +17,7 @@ export function configureAuthenticationServer(config) {
18
17
  if (isDefined(config.authenticationService)) {
19
18
  Injector.registerSingleton(AuthenticationService, { useToken: config.authenticationService });
20
19
  }
21
- if (isDefined(config.tokenPayloadProvider)) {
22
- Injector.registerSingleton(AuthenticationTokenPayloadProvider, { useToken: config.tokenPayloadProvider });
23
- }
24
- if (isDefined(config.subjectResolver)) {
25
- Injector.registerSingleton(AuthenticationSubjectResolver, { useToken: config.subjectResolver });
20
+ if (isDefined(config.authenticationAncillaryService)) {
21
+ Injector.registerSingleton(AuthenticationAncillaryService, { useToken: config.authenticationAncillaryService });
26
22
  }
27
23
  }
@@ -13,7 +13,7 @@ import { Agent } from 'undici';
13
13
  import { configureApiServer } from '../../api/server/index.js';
14
14
  import { Application } from '../../application/application.js';
15
15
  import { AuthenticationClientService, configureAuthenticationClient, getAuthenticationApiClient } from '../../authentication/client/index.js';
16
- import { AuthenticationTokenPayloadProvider } from '../../authentication/server/authentication-token-payload.provider.js';
16
+ import { AuthenticationAncillaryService } from '../../authentication/index.js';
17
17
  import { AuthenticationApiController } from '../../authentication/server/authentication.api-controller.js';
18
18
  import { AuthenticationService as AuthenticationServerService } from '../../authentication/server/authentication.service.js';
19
19
  import { configureAuthenticationServer } from '../../authentication/server/module.js';
@@ -68,14 +68,23 @@ __decorate([
68
68
  __metadata("design:type", String)
69
69
  ], AuthenticationData.prototype, "deviceId", void 0);
70
70
  const CustomAuthenticationApiClient = getAuthenticationApiClient(CustomTokenPaylod, AuthenticationData, emptyObjectSchema);
71
- let CustomTokenPayloadProvider = class CustomTokenPayloadProvider extends AuthenticationTokenPayloadProvider {
71
+ let CustomAuthenticationAncillaryService = class CustomAuthenticationAncillaryService extends AuthenticationAncillaryService {
72
72
  getTokenPayload(_subject, authenticationData) {
73
73
  return { deviceRegistrationId: `registration:${authenticationData.deviceId}` };
74
74
  }
75
+ resolveSubject() {
76
+ throw new Error('Method not implemented.');
77
+ }
78
+ handleInitSecretReset() {
79
+ throw new Error('Method not implemented.');
80
+ }
81
+ canImpersonate() {
82
+ throw new Error('Method not implemented.');
83
+ }
75
84
  };
76
- CustomTokenPayloadProvider = __decorate([
85
+ CustomAuthenticationAncillaryService = __decorate([
77
86
  Singleton()
78
- ], CustomTokenPayloadProvider);
87
+ ], CustomAuthenticationAncillaryService);
79
88
  async function serverTest() {
80
89
  const authenticationService = await injectAsync(AuthenticationServerService);
81
90
  await authenticationService.setCredentials('foobar', 'supersecret-dupidupudoo9275');
@@ -101,7 +110,7 @@ function bootstrap() {
101
110
  serviceOptions: { secret: 'djp0fq23576aq' },
102
111
  credentialsRepository: MongoAuthenticationCredentialsRepository,
103
112
  sessionRepository: MongoAuthenticationSessionRepository,
104
- tokenPayloadProvider: CustomTokenPayloadProvider
113
+ authenticationAncillaryService: CustomAuthenticationAncillaryService
105
114
  });
106
115
  configureMongoAuthenticationCredentialsRepository({ collection: 'credentials' });
107
116
  configureMongoAuthenticationSessionRepository({ collection: 'sessions' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.90.36",
3
+ "version": "0.90.38",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,4 +0,0 @@
1
- import type { InitSecretResetData } from '../models/init-secret-reset-data.model.js';
2
- export declare abstract class AuthenticationSecretResetHandler<AdditionalInitSecretResetData> {
3
- abstract handleInitSecretReset(data: InitSecretResetData & AdditionalInitSecretResetData): void | Promise<void>;
4
- }
@@ -1,2 +0,0 @@
1
- export class AuthenticationSecretResetHandler {
2
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Resolve a provided subject to the actual subject used for authentication.
3
- * Useful for example if you want to be able to login via mail but actual subject is the user id.
4
- */
5
- export declare abstract class AuthenticationSubjectResolver {
6
- abstract resolveSubject(providedSubject: string): string | Promise<string>;
7
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Resolve a provided subject to the actual subject used for authentication.
3
- * Useful for example if you want to be able to login via mail but actual subject is the user id.
4
- */
5
- export class AuthenticationSubjectResolver {
6
- }
@@ -1,11 +0,0 @@
1
- import type { Record } from '../../types.js';
2
- export declare enum GetTokenPayloadContextAction {
3
- GetToken = 0,
4
- Refresh = 1
5
- }
6
- export type GetTokenPayloadContext = {
7
- action: GetTokenPayloadContextAction;
8
- };
9
- export declare abstract class AuthenticationTokenPayloadProvider<AdditionalTokenPayload = Record<never>, AuthenticationData = void> {
10
- abstract getTokenPayload(subject: string, authenticationData: AuthenticationData, context: GetTokenPayloadContext): AdditionalTokenPayload | Promise<AdditionalTokenPayload>;
11
- }