@wbce-d9/api 12.3.0 → 12.4.2

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.
@@ -1,4 +1,4 @@
1
- import type { Client, TokenSet } from 'openid-client';
1
+ import * as oidc from 'openid-client';
2
2
  import { UsersService } from '../../services/users.js';
3
3
  import type { User } from '../../types/index.js';
4
4
  import { LocalAuthDriver } from './local.js';
@@ -12,12 +12,12 @@ export interface UserPayload {
12
12
  auth_data: any;
13
13
  }
14
14
  export declare abstract class BaseOAuthDriver extends LocalAuthDriver {
15
- abstract getClient(): Promise<Client>;
15
+ abstract getClient(): Promise<oidc.Configuration>;
16
16
  abstract getredirectUrl(): string;
17
17
  abstract getUserService(): UsersService;
18
18
  abstract getConfig(): Record<string, any>;
19
19
  abstract getClientName(): string;
20
- abstract getTokenSetAndUserInfo(payload: Record<string, any>): Promise<[TokenSet, Record<string, unknown>, UserPayload]>;
20
+ abstract getTokenSetAndUserInfo(payload: Record<string, any>): Promise<[oidc.TokenEndpointResponse & oidc.TokenEndpointResponseHelpers, Record<string, unknown>, UserPayload]>;
21
21
  generateCodeVerifier(): string;
22
22
  fetchUserId(identifier: string): Promise<string | undefined>;
23
23
  getUserID(payload: Record<string, any>): Promise<string>;
@@ -1,5 +1,5 @@
1
1
  import { parseJSON } from '@wbce-d9/utils';
2
- import { errors, generators } from 'openid-client';
2
+ import * as oidc from 'openid-client';
3
3
  import getDatabase from '../../database/index.js';
4
4
  import emitter from '../../emitter.js';
5
5
  import { RecordNotUniqueException } from '../../exceptions/database/record-not-unique.js';
@@ -9,7 +9,7 @@ import { UsersService } from '../../services/users.js';
9
9
  import { LocalAuthDriver } from './local.js';
10
10
  export class BaseOAuthDriver extends LocalAuthDriver {
11
11
  generateCodeVerifier() {
12
- return generators.codeVerifier();
12
+ return oidc.randomPKCECodeVerifier();
13
13
  }
14
14
  async fetchUserId(identifier) {
15
15
  const user = await this.knex.select('id').from('directus_users').where('external_identifier', identifier).first();
@@ -86,9 +86,9 @@ export class BaseOAuthDriver extends LocalAuthDriver {
86
86
  if (authData?.['refreshToken']) {
87
87
  try {
88
88
  const client = await this.getClient();
89
- const tokenSet = await client.refresh(authData['refreshToken']);
89
+ const tokenSet = await oidc.refreshTokenGrant(client, authData['refreshToken']);
90
90
  if (tokenSet.refresh_token) {
91
- await client.revoke(tokenSet.refresh_token, 'refresh_token');
91
+ await oidc.tokenRevocation(client, tokenSet.refresh_token);
92
92
  }
93
93
  await this.getUserService().updateOne(user.id, {
94
94
  auth_data: null,
@@ -119,7 +119,7 @@ export class BaseOAuthDriver extends LocalAuthDriver {
119
119
  if (authData?.['refreshToken']) {
120
120
  try {
121
121
  const client = await this.getClient();
122
- const tokenSet = await client.refresh(authData['refreshToken']);
122
+ const tokenSet = await oidc.refreshTokenGrant(client, authData['refreshToken']);
123
123
  // Update user refreshToken if provided
124
124
  if (tokenSet.refresh_token) {
125
125
  await this.getUserService().updateOne(user.id, {
@@ -138,7 +138,7 @@ export class BaseOAuthDriver extends LocalAuthDriver {
138
138
  }
139
139
  }
140
140
  handleError = (e) => {
141
- if (e instanceof errors.OPError) {
141
+ if (e instanceof oidc.ResponseBodyError) {
142
142
  if (e.error === 'invalid_grant') {
143
143
  // Invalid token
144
144
  logger.trace(e, `[${this.getClientName()}] Invalid grant`);
@@ -151,7 +151,7 @@ export class BaseOAuthDriver extends LocalAuthDriver {
151
151
  message: e.error_description,
152
152
  });
153
153
  }
154
- else if (e instanceof errors.RPError) {
154
+ else if (e instanceof oidc.ClientError) {
155
155
  // Internal client error
156
156
  logger.trace(e, `[${this.getClientName()}] Unknown RP error`);
157
157
  return new InvalidCredentialsException();
@@ -1,20 +1,20 @@
1
1
  import { Router } from 'express';
2
- import type { BaseClient, Client, TokenSet } from 'openid-client';
2
+ import * as oidc from 'openid-client';
3
3
  import { UsersService } from '../../services/users.js';
4
4
  import type { AuthDriverOptions } from '../../types/index.js';
5
5
  import { BaseOAuthDriver, type UserPayload } from './baseoauth.js';
6
6
  export declare class OAuth2AuthDriver extends BaseOAuthDriver {
7
- client: Client;
7
+ client: oidc.Configuration;
8
8
  redirectUrl: string;
9
9
  usersService: UsersService;
10
10
  config: Record<string, any>;
11
- getClient(): Promise<BaseClient>;
11
+ getClient(): Promise<oidc.Configuration>;
12
12
  getredirectUrl(): string;
13
13
  getUserService(): UsersService;
14
14
  getConfig(): Record<string, any>;
15
15
  getClientName(): string;
16
16
  constructor(options: AuthDriverOptions, config: Record<string, any>);
17
- generateAuthUrl(codeVerifier: string, prompt?: boolean): string;
18
- getTokenSetAndUserInfo(payload: Record<string, any>): Promise<[TokenSet, Record<string, unknown>, UserPayload]>;
17
+ generateAuthUrl(codeVerifier: string, prompt?: boolean): Promise<string>;
18
+ getTokenSetAndUserInfo(payload: Record<string, any>): Promise<[oidc.TokenEndpointResponse & oidc.TokenEndpointResponseHelpers, Record<string, unknown>, UserPayload]>;
19
19
  }
20
20
  export declare function createOAuth2AuthRouter(providerName: string): Router;
@@ -2,9 +2,9 @@ import { BaseException } from '@wbce-d9/exceptions';
2
2
  import express, { Router } from 'express';
3
3
  import flatten from 'flat';
4
4
  import jwt from 'jsonwebtoken';
5
- import { Issuer, generators } from 'openid-client';
5
+ import * as oidc from 'openid-client';
6
6
  import { getAuthProvider } from '../../auth.js';
7
- import { ACCESS_COOKIE_OPTIONS, OAUTH2_COOKIE_CLEAR_OPTIONS, OAUTH2_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS, } from '../../constants.js';
7
+ import { ACCESS_COOKIE_OPTIONS, OAUTH2_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS } from '../../constants.js';
8
8
  import env from '../../env.js';
9
9
  import { InvalidConfigException, InvalidCredentialsException, InvalidTokenException, InvalidPayloadException, } from '../../exceptions/index.js';
10
10
  import logger from '../../logger.js';
@@ -47,35 +47,31 @@ export class OAuth2AuthDriver extends BaseOAuthDriver {
47
47
  this.redirectUrl = redirectUrl.toString();
48
48
  this.usersService = new UsersService({ knex: this.knex, schema: this.schema });
49
49
  this.config = additionalConfig;
50
- const issuer = new Issuer({
50
+ const clientOptionsOverrides = getConfigFromEnv(`AUTH_${config['provider'].toUpperCase()}_CLIENT_`, [`AUTH_${config['provider'].toUpperCase()}_CLIENT_ID`, `AUTH_${config['provider'].toUpperCase()}_CLIENT_SECRET`], 'underscore');
51
+ this.client = new oidc.Configuration({
51
52
  authorization_endpoint: authorizeUrl,
52
53
  token_endpoint: accessUrl,
53
54
  userinfo_endpoint: profileUrl,
54
55
  issuer: additionalConfig['provider'],
55
- });
56
- const clientOptionsOverrides = getConfigFromEnv(`AUTH_${config['provider'].toUpperCase()}_CLIENT_`, [`AUTH_${config['provider'].toUpperCase()}_CLIENT_ID`, `AUTH_${config['provider'].toUpperCase()}_CLIENT_SECRET`], 'underscore');
57
- this.client = new issuer.Client({
58
- client_id: clientId,
59
- client_secret: clientSecret,
60
- redirect_uris: [this.redirectUrl],
61
- response_types: ['code'],
62
- ...clientOptionsOverrides,
63
- });
56
+ }, clientId, { client_secret: clientSecret, ...clientOptionsOverrides });
64
57
  }
65
- generateAuthUrl(codeVerifier, prompt = false) {
58
+ async generateAuthUrl(codeVerifier, prompt = false) {
66
59
  try {
67
- const codeChallenge = generators.codeChallenge(codeVerifier);
60
+ const codeChallenge = await oidc.calculatePKCECodeChallenge(codeVerifier);
68
61
  const paramsConfig = typeof this.config['params'] === 'object' ? this.config['params'] : {};
69
- return this.client.authorizationUrl({
62
+ const params = {
70
63
  scope: this.config['scope'] ?? 'email',
71
64
  access_type: 'offline',
72
- prompt: prompt ? 'consent' : undefined,
73
65
  ...paramsConfig,
74
66
  code_challenge: codeChallenge,
75
67
  code_challenge_method: 'S256',
76
68
  // Some providers require state even with PKCE
77
69
  state: codeChallenge,
78
- });
70
+ };
71
+ if (prompt) {
72
+ params['prompt'] = 'consent';
73
+ }
74
+ return oidc.buildAuthorizationUrl(this.client, params).href;
79
75
  }
80
76
  catch (e) {
81
77
  throw this.handleError(e);
@@ -85,8 +81,13 @@ export class OAuth2AuthDriver extends BaseOAuthDriver {
85
81
  let tokenSet;
86
82
  let userInfo;
87
83
  try {
88
- tokenSet = await this.client.oauthCallback(this.redirectUrl, { code: payload['code'], state: payload['state'] }, { code_verifier: payload['codeVerifier'], state: generators.codeChallenge(payload['codeVerifier']) });
89
- userInfo = await this.client.userinfo(tokenSet.access_token);
84
+ const codeChallenge = await oidc.calculatePKCECodeChallenge(payload['codeVerifier']);
85
+ const callbackUrl = new URL(payload['callbackPath'], this.redirectUrl);
86
+ tokenSet = await oidc.authorizationCodeGrant(this.client, callbackUrl, {
87
+ pkceCodeVerifier: payload['codeVerifier'],
88
+ expectedState: codeChallenge,
89
+ });
90
+ userInfo = await oidc.fetchUserInfo(this.client, tokenSet.access_token, oidc.skipSubjectCheck);
90
91
  }
91
92
  catch (e) {
92
93
  throw this.handleError(e);
@@ -115,7 +116,7 @@ export class OAuth2AuthDriver extends BaseOAuthDriver {
115
116
  }
116
117
  export function createOAuth2AuthRouter(providerName) {
117
118
  const router = Router();
118
- router.get('/', (req, res) => {
119
+ router.get('/', asyncHandler(async (req, res) => {
119
120
  const provider = getAuthProvider(providerName);
120
121
  const codeVerifier = provider.generateCodeVerifier();
121
122
  const prompt = !!req.query['prompt'];
@@ -124,12 +125,12 @@ export function createOAuth2AuthRouter(providerName) {
124
125
  throw new InvalidPayloadException(`URL "${redirect}" can't be used to redirect after login`);
125
126
  }
126
127
  const token = jwt.sign({ verifier: codeVerifier, redirect, prompt }, env['SECRET'], {
127
- expiresIn: '5m',
128
+ expiresIn: Math.floor(OAUTH2_COOKIE_OPTIONS.maxAge / 1000),
128
129
  issuer: 'directus',
129
130
  });
130
131
  res.cookie(`oauth2.${providerName}`, token, OAUTH2_COOKIE_OPTIONS);
131
- return res.redirect(provider.generateAuthUrl(codeVerifier, prompt));
132
- }, respond);
132
+ return res.redirect(await provider.generateAuthUrl(codeVerifier, prompt));
133
+ }), respond);
133
134
  router.post('/callback', express.urlencoded({ extended: false }), (req, res) => {
134
135
  res.redirect(303, `./callback?${new URLSearchParams(req.body)}`);
135
136
  }, respond);
@@ -161,8 +162,8 @@ export function createOAuth2AuthRouter(providerName) {
161
162
  });
162
163
  let authResponse;
163
164
  try {
164
- res.clearCookie(`oauth2.${providerName}`, OAUTH2_COOKIE_CLEAR_OPTIONS);
165
165
  authResponse = await authenticationService.login(providerName, {
166
+ callbackPath: req.originalUrl,
166
167
  code: req.query['code'],
167
168
  codeVerifier: verifier,
168
169
  state: req.query['state'],
@@ -1,20 +1,20 @@
1
1
  import { Router } from 'express';
2
- import type { AuthorizationParameters, BaseClient, Client, TokenSet } from 'openid-client';
2
+ import * as oidc from 'openid-client';
3
3
  import { UsersService } from '../../services/users.js';
4
4
  import type { AuthDriverOptions } from '../../types/index.js';
5
5
  import { BaseOAuthDriver, type UserPayload } from './baseoauth.js';
6
6
  export declare class OpenIDAuthDriver extends BaseOAuthDriver {
7
- client: Promise<Client>;
7
+ client: Promise<oidc.Configuration>;
8
8
  redirectUrl: string;
9
9
  usersService: UsersService;
10
10
  config: Record<string, any>;
11
- getClient(): Promise<BaseClient>;
11
+ getClient(): Promise<oidc.Configuration>;
12
12
  getredirectUrl(): string;
13
13
  getUserService(): UsersService;
14
14
  getConfig(): Record<string, any>;
15
15
  getClientName(): string;
16
16
  constructor(options: AuthDriverOptions, config: Record<string, any>);
17
- generateAuthUrl(codeVerifier: string, prompt?: boolean, additionalParams?: AuthorizationParameters | undefined): Promise<string>;
18
- getTokenSetAndUserInfo(payload: Record<string, any>): Promise<[TokenSet, Record<string, unknown>, UserPayload]>;
17
+ generateAuthUrl(codeVerifier: string, prompt?: boolean, additionalParams?: Record<string, string>): Promise<string>;
18
+ getTokenSetAndUserInfo(payload: Record<string, any>): Promise<[oidc.TokenEndpointResponse & oidc.TokenEndpointResponseHelpers, Record<string, unknown>, UserPayload]>;
19
19
  }
20
20
  export declare function createOpenIDAuthRouter(providerName: string): Router;
@@ -2,9 +2,9 @@ import { BaseException } from '@wbce-d9/exceptions';
2
2
  import express, { Router } from 'express';
3
3
  import flatten from 'flat';
4
4
  import jwt from 'jsonwebtoken';
5
- import { Issuer, generators } from 'openid-client';
5
+ import * as oidc from 'openid-client';
6
6
  import { getAuthProvider } from '../../auth.js';
7
- import { ACCESS_COOKIE_OPTIONS, OAUTH2_COOKIE_CLEAR_OPTIONS, OAUTH2_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS, } from '../../constants.js';
7
+ import { ACCESS_COOKIE_OPTIONS, OAUTH2_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS } from '../../constants.js';
8
8
  import env from '../../env.js';
9
9
  import { InvalidConfigException, InvalidCredentialsException, InvalidTokenException, InvalidPayloadException, } from '../../exceptions/index.js';
10
10
  import logger from '../../logger.js';
@@ -48,55 +48,48 @@ export class OpenIDAuthDriver extends BaseOAuthDriver {
48
48
  this.redirectUrl = redirectUrl.toString();
49
49
  this.usersService = new UsersService({ knex: this.knex, schema: this.schema });
50
50
  this.config = additionalConfig;
51
- this.client = new Promise((resolve, reject) => {
52
- Issuer.discover(issuerUrl)
53
- .then((issuer) => {
54
- const supportedTypes = issuer.metadata['response_types_supported'];
55
- if (!supportedTypes?.includes('code')) {
56
- reject(new InvalidConfigException('OpenID provider does not support required code flow', {
57
- provider: additionalConfig['provider'],
58
- }));
59
- }
60
- resolve(new issuer.Client({
61
- client_id: clientId,
51
+ this.client = (async () => {
52
+ let config;
53
+ try {
54
+ config = await oidc.discovery(new URL(issuerUrl), clientId, {
62
55
  client_secret: clientSecret,
63
- redirect_uris: [this.redirectUrl],
64
- response_types: ['code'],
65
56
  ...clientOptionsOverrides,
66
- }));
67
- })
68
- .catch((e) => {
57
+ });
58
+ }
59
+ catch (e) {
69
60
  logger.error(e, '[OpenID] Failed to fetch provider config');
70
61
  process.exit(1);
71
- });
72
- });
62
+ }
63
+ const supportedTypes = config.serverMetadata().response_types_supported;
64
+ if (supportedTypes && !supportedTypes.includes('code')) {
65
+ throw new InvalidConfigException('OpenID provider does not support required code flow', {
66
+ provider: additionalConfig['provider'],
67
+ });
68
+ }
69
+ return config;
70
+ })();
73
71
  }
74
72
  async generateAuthUrl(codeVerifier, prompt = false, additionalParams) {
75
73
  try {
76
74
  const client = await this.client;
77
- const codeChallenge = generators.codeChallenge(codeVerifier);
75
+ const codeChallenge = await oidc.calculatePKCECodeChallenge(codeVerifier);
78
76
  const paramsConfig = typeof this.config['params'] === 'object' ? this.config['params'] : {};
79
- const redirectAfterLogin = additionalParams?.['redirect'];
80
- delete additionalParams?.['redirect'];
81
- let finalRedirectUri = this.redirectUrl;
82
- if (redirectAfterLogin) {
83
- const redirectUriWithParams = new URL(this.redirectUrl);
84
- redirectUriWithParams.searchParams.set('redirect', redirectAfterLogin);
85
- finalRedirectUri = redirectUriWithParams.toString();
86
- }
87
- return client.authorizationUrl({
77
+ const params = {
88
78
  scope: this.config['scope'] ?? 'openid profile email',
89
79
  access_type: 'offline',
90
- prompt: prompt ? 'consent' : undefined,
91
80
  ...paramsConfig,
92
81
  code_challenge: codeChallenge,
93
82
  code_challenge_method: 'S256',
94
83
  // Some providers require state even with PKCE
95
84
  state: codeChallenge,
96
85
  nonce: codeChallenge,
97
- redirect_uri: finalRedirectUri,
86
+ redirect_uri: this.redirectUrl,
98
87
  ...additionalParams,
99
- });
88
+ };
89
+ if (prompt) {
90
+ params.prompt = 'consent';
91
+ }
92
+ return oidc.buildAuthorizationUrl(client, params).href;
100
93
  }
101
94
  catch (e) {
102
95
  throw this.handleError(e);
@@ -107,19 +100,18 @@ export class OpenIDAuthDriver extends BaseOAuthDriver {
107
100
  let userInfo;
108
101
  try {
109
102
  const client = await this.client;
110
- const codeChallenge = generators.codeChallenge(payload['codeVerifier']);
111
- let finalRedirectUri = this.redirectUrl;
112
- if (payload['redirect']) {
113
- const redirectUriWithParams = new URL(this.redirectUrl);
114
- redirectUriWithParams.searchParams.set('redirect', payload['redirect']);
115
- finalRedirectUri = redirectUriWithParams.toString();
116
- }
117
- tokenSet = await client.callback(finalRedirectUri, { code: payload['code'], state: payload['state'], iss: payload['iss'] }, { code_verifier: payload['codeVerifier'], state: codeChallenge, nonce: codeChallenge });
118
- userInfo = tokenSet.claims();
119
- if (client.issuer.metadata['userinfo_endpoint']) {
103
+ const codeChallenge = await oidc.calculatePKCECodeChallenge(payload['codeVerifier']);
104
+ const callbackUrl = new URL(payload['callbackPath'], this.redirectUrl);
105
+ tokenSet = await oidc.authorizationCodeGrant(client, callbackUrl, {
106
+ pkceCodeVerifier: payload['codeVerifier'],
107
+ expectedState: codeChallenge,
108
+ expectedNonce: codeChallenge,
109
+ });
110
+ userInfo = (tokenSet.claims() ?? {});
111
+ if (client.serverMetadata().userinfo_endpoint) {
120
112
  userInfo = {
121
113
  ...userInfo,
122
- ...(await client.userinfo(tokenSet.access_token)),
114
+ ...(await oidc.fetchUserInfo(client, tokenSet.access_token, tokenSet.claims()?.sub ?? oidc.skipSubjectCheck)),
123
115
  };
124
116
  }
125
117
  }
@@ -159,11 +151,12 @@ export function createOpenIDAuthRouter(providerName) {
159
151
  throw new InvalidPayloadException(`URL "${redirect}" can't be used to redirect after login`);
160
152
  }
161
153
  const token = jwt.sign({ verifier: codeVerifier, redirect, prompt }, env['SECRET'], {
162
- expiresIn: '5m',
154
+ expiresIn: Math.floor(OAUTH2_COOKIE_OPTIONS.maxAge / 1000),
163
155
  issuer: 'directus',
164
156
  });
165
- const additionalParams = { ...req.query };
166
- delete additionalParams['prompt'];
157
+ const additionalParams = Object.fromEntries(Object.entries(req.query)
158
+ .filter(([k, v]) => k !== 'prompt' && k !== 'redirect' && typeof v === 'string')
159
+ .map(([k, v]) => [k, v]));
167
160
  const authUrl = await provider.generateAuthUrl(codeVerifier, prompt, additionalParams);
168
161
  const urlParams = new URL(authUrl);
169
162
  const state = urlParams.searchParams.get('state');
@@ -211,13 +204,13 @@ export function createOpenIDAuthRouter(providerName) {
211
204
  });
212
205
  let authResponse;
213
206
  try {
214
- res.clearCookie(cookieName, OAUTH2_COOKIE_CLEAR_OPTIONS);
215
207
  authResponse = await authenticationService.login(providerName, {
216
208
  code: req.query['code'],
217
209
  codeVerifier: verifier,
218
210
  state: req.query['state'],
219
211
  iss: req.query['iss'],
220
212
  redirect: validRedirectUrl,
213
+ callbackPath: req.originalUrl,
221
214
  });
222
215
  }
223
216
  catch (error) {
package/dist/constants.js CHANGED
@@ -85,7 +85,7 @@ export const ACCESS_COOKIE_CLEAR_OPTIONS = (() => {
85
85
  export const OAUTH2_COOKIE_OPTIONS = {
86
86
  httpOnly: true,
87
87
  domain: env['OAUTH2_TOKEN_COOKIE_DOMAIN'] || env['ACCESS_TOKEN_COOKIE_DOMAIN'],
88
- maxAge: getMilliseconds(env['OAUTH2_TOKEN_TTL'] || env['ACCESS_TOKEN_TTL']),
88
+ maxAge: getMilliseconds(env['OAUTH2_TOKEN_TTL']),
89
89
  secure: (env['OAUTH2_TOKEN_COOKIE_SECURE'] || env['ACCESS_TOKEN_COOKIE_SECURE']) ?? false,
90
90
  sameSite: env['OAUTH2_TOKEN_COOKIE_SAME_SITE'] || 'lax',
91
91
  path: '/auth',
package/dist/env.js CHANGED
@@ -49,6 +49,10 @@ const allowedEnvironmentVars = [
49
49
  'REFRESH_TOKEN_COOKIE_SAME_SITE',
50
50
  'REFRESH_TOKEN_COOKIE_NAME',
51
51
  'REFRESH_TOKEN_OVERLAP_DURATION',
52
+ 'OAUTH2_TOKEN_TTL',
53
+ 'OAUTH2_TOKEN_COOKIE_DOMAIN',
54
+ 'OAUTH2_TOKEN_COOKIE_SECURE',
55
+ 'OAUTH2_TOKEN_COOKIE_SAME_SITE',
52
56
  'LOGIN_STALL_TIME',
53
57
  'PASSWORD_RESET_URL_ALLOW_LIST',
54
58
  'USER_INVITE_URL_ALLOW_LIST',
@@ -235,6 +239,7 @@ const defaults = {
235
239
  REFRESH_TOKEN_COOKIE_SAME_SITE: 'lax',
236
240
  REFRESH_TOKEN_COOKIE_NAME: 'directus_refresh_token',
237
241
  REFRESH_TOKEN_OVERLAP_DURATION: '10s',
242
+ OAUTH2_TOKEN_TTL: '1d',
238
243
  LOGIN_STALL_TIME: 500,
239
244
  SERVER_SHUTDOWN_TIMEOUT: 1000,
240
245
  ROOT_REDIRECT: './admin',
@@ -7,7 +7,7 @@ export class ForbiddenException extends BaseException {
7
7
  * We currently don't show the reason for a forbidden exception in the API output, as that
8
8
  * has the potential to leak schema information (eg a "No permission" vs "No permission to files"
9
9
  * would leak that a thing called "files" exists.
10
- * Ref https://github.com/LaWebcapsule/directus9/discussions/4368
10
+ * Ref https://github.com/LaWebcapsule/d9/discussions/4368
11
11
  */
12
12
  }
13
13
  }
@@ -1,7 +1,7 @@
1
1
  import argon2 from 'argon2';
2
2
  import { getConfigFromEnv } from './get-config-from-env.js';
3
3
  export function generateHash(stringToHash) {
4
- const argon2HashConfigOptions = getConfigFromEnv('HASH_', 'HASH_RAW'); // Disallow the HASH_RAW option, see https://github.com/LaWebcapsule/directus9/discussions/7670#discussioncomment-1255805
4
+ const argon2HashConfigOptions = getConfigFromEnv('HASH_', 'HASH_RAW'); // Disallow the HASH_RAW option, see https://github.com/LaWebcapsule/d9/discussions/7670#discussioncomment-1255805
5
5
  // associatedData, if specified, must be passed as a Buffer to argon2.hash, see https://github.com/ranisalt/node-argon2/wiki/Options#associateddata
6
6
  'associatedData' in argon2HashConfigOptions &&
7
7
  (argon2HashConfigOptions['associatedData'] = Buffer.from(argon2HashConfigOptions['associatedData']));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wbce-d9/api",
3
- "version": "12.3.0",
3
+ "version": "12.4.2",
4
4
  "description": "Directus is a real-time API and App dashboard for managing SQL database content",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -22,16 +22,16 @@
22
22
  "framework",
23
23
  "vue"
24
24
  ],
25
- "homepage": "https://github.com/LaWebcapsule/directus9",
25
+ "homepage": "https://github.com/LaWebcapsule/d9",
26
26
  "bugs": {
27
- "url": "https://github.com/LaWebcapsule/directus9/issues"
27
+ "url": "https://github.com/LaWebcapsule/d9/issues"
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
31
- "url": "https://github.com/LaWebcapsule/directus9.git",
31
+ "url": "https://github.com/LaWebcapsule/d9.git",
32
32
  "directory": "api"
33
33
  },
34
- "funding": "https://github.com/LaWebcapsule/directus9?sponsor=1",
34
+ "funding": "https://github.com/LaWebcapsule/d9?sponsor=1",
35
35
  "license": "GPL-3.0-only",
36
36
  "author": {
37
37
  "name": "Monospace Inc",
@@ -85,7 +85,7 @@
85
85
  "openapi3-ts": "3.2.0",
86
86
  "ora": "6.3.0",
87
87
  "pino": "8.11.0",
88
- "rollup": "3.29.5",
88
+ "rollup": "3.30.0",
89
89
  "uuid": "9.0.0",
90
90
  "wellknown": "0.5.0",
91
91
  "@authenio/samlify-node-xmllint": "2.0.0",
@@ -127,7 +127,7 @@
127
127
  "node-machine-id": "1.1.12",
128
128
  "nodemailer": "7.0.11",
129
129
  "object-hash": "3.0.0",
130
- "openid-client": "5.4.0",
130
+ "openid-client": "6.8.2",
131
131
  "otplib": "12.0.1",
132
132
  "pino-http": "8.3.3",
133
133
  "pino-http-print": "3.1.0",
@@ -143,20 +143,20 @@
143
143
  "tmp-promise": "3.0.3",
144
144
  "tsx": "3.12.6",
145
145
  "uuid-validate": "0.0.3",
146
- "@wbce-d9/app": "10.0.0",
147
- "@wbce-d9/exceptions": "10.0.0",
148
- "@wbce-d9/extensions-sdk": "10.0.2",
146
+ "@wbce-d9/app": "10.0.2",
149
147
  "@wbce-d9/constants": "10.0.0",
148
+ "@wbce-d9/exceptions": "10.0.0",
150
149
  "@wbce-d9/schema": "10.0.0",
151
150
  "@wbce-d9/specs": "9.26.5",
152
151
  "@wbce-d9/storage": "10.0.0",
153
152
  "@wbce-d9/storage-driver-azure": "10.0.1",
153
+ "@wbce-d9/storage-driver-cloudinary": "10.0.1",
154
+ "@wbce-d9/extensions-sdk": "10.0.2",
154
155
  "@wbce-d9/storage-driver-gcs": "10.0.1",
155
- "@wbce-d9/storage-driver-s3": "10.0.1",
156
156
  "@wbce-d9/storage-driver-local": "10.0.1",
157
- "@wbce-d9/utils": "10.0.1",
157
+ "@wbce-d9/storage-driver-s3": "10.0.1",
158
158
  "@wbce-d9/update-check": "10.0.1",
159
- "@wbce-d9/storage-driver-cloudinary": "10.0.1"
159
+ "@wbce-d9/utils": "10.0.1"
160
160
  },
161
161
  "devDependencies": {
162
162
  "@ngneat/falso": "6.4.0",
@@ -170,11 +170,11 @@
170
170
  "@types/supertest": "2.0.12",
171
171
  "@types/uuid": "9.0.1",
172
172
  "@types/wellknown": "0.5.4",
173
- "@vitest/coverage-v8": "4.1.0",
173
+ "@vitest/coverage-v8": "4.1.4",
174
174
  "@wbce-d9/tsconfig": "2.0.0",
175
175
  "supertest": "6.3.3",
176
176
  "typescript": "5.0.4",
177
- "vitest": "4.1.0",
177
+ "vitest": "4.1.4",
178
178
  "@types/async": "3.2.19",
179
179
  "@types/busboy": "1.5.0",
180
180
  "@types/bytes": "3.1.1",