diff --git a/.changeset/late-lions-pump.md b/.changeset/late-lions-pump.md new file mode 100644 index 0000000000..192eebb481 --- /dev/null +++ b/.changeset/late-lions-pump.md @@ -0,0 +1,5 @@ +--- +"@directus/api": patch +--- + +Improved session token validation diff --git a/api/src/utils/get-accountability-for-token.ts b/api/src/utils/get-accountability-for-token.ts index a81f59623a..d4a4800107 100644 --- a/api/src/utils/get-accountability-for-token.ts +++ b/api/src/utils/get-accountability-for-token.ts @@ -3,6 +3,7 @@ import { InvalidCredentialsError } from '@directus/errors'; import type { Accountability } from '@directus/types'; import getDatabase from '../database/index.js'; import isDirectusJWT from './is-directus-jwt.js'; +import { verifySessionJWT } from './verify-session-jwt.js'; import { verifyAccessJWT } from './jwt.js'; export async function getAccountabilityForToken( @@ -24,6 +25,10 @@ export async function getAccountabilityForToken( if (isDirectusJWT(token)) { const payload = verifyAccessJWT(token, env['SECRET'] as string); + if ('session' in payload) { + await verifySessionJWT(payload); + } + accountability.role = payload.role; accountability.admin = payload.admin_access === true || payload.admin_access == 1; accountability.app = payload.app_access === true || payload.app_access == 1; diff --git a/api/src/utils/verify-session-jwt.ts b/api/src/utils/verify-session-jwt.ts new file mode 100644 index 0000000000..3a6bdeef2b --- /dev/null +++ b/api/src/utils/verify-session-jwt.ts @@ -0,0 +1,26 @@ +import getDatabase from '../database/index.js'; +import { InvalidTokenError } from '@directus/errors'; +import type { DirectusTokenPayload } from '../types/index.js'; + +/** + * Verifies the associated session is still available and valid. + * + * @throws If session not found. + */ +export async function verifySessionJWT(payload: DirectusTokenPayload) { + const database = getDatabase(); + + const session = await database + .select(1) + .from('directus_sessions') + .where({ + token: payload['session'], + user: payload['id'], + }) + .andWhere('expires', '>=', new Date()) + .first(); + + if (!session) { + throw new InvalidTokenError(); + } +}