From fd2ea4a24ea7e24b513c066fdf985102638f839c Mon Sep 17 00:00:00 2001 From: Darcy Ye Date: Thu, 26 Dec 2024 12:22:17 +0800 Subject: [PATCH] chore: update code --- .../src/saml-applications/queries/sessions.ts | 69 +++++++++++-------- ...422-add-saml-application-sessions-table.ts | 11 +-- .../tables/saml_application_sessions.sql | 15 +--- 3 files changed, 45 insertions(+), 50 deletions(-) diff --git a/packages/core/src/saml-applications/queries/sessions.ts b/packages/core/src/saml-applications/queries/sessions.ts index c5e728f85..7d96d9862 100644 --- a/packages/core/src/saml-applications/queries/sessions.ts +++ b/packages/core/src/saml-applications/queries/sessions.ts @@ -4,6 +4,7 @@ import { sql } from '@silverhand/slonik'; import { buildInsertIntoWithPool } from '#src/database/insert-into.js'; import { buildUpdateWhereWithPool } from '#src/database/update-where.js'; +import { DeletionError } from '#src/errors/SlonikError/index.js'; import { convertToIdentifiers } from '#src/utils/sql.js'; const { table, fields } = convertToIdentifiers(SamlApplicationSessions); @@ -15,16 +16,48 @@ export const createSamlApplicationSessionQueries = (pool: CommonQueryMethods) => const updateSession = buildUpdateWhereWithPool(pool)(SamlApplicationSessions, true); - const deleteExpiredOrFullyUsedSessions = async () => { + /** + * Removes the OIDC state from a session, which marks OIDC state as consumed. + * + * @param id The ID of the session. + * @returns The updated session. + */ + const removeSessionOidcStateById = async (id: string) => + updateSession({ + set: { oidcState: null }, + where: { id }, + jsonbMode: 'merge', + }); + + const deleteExpiredSessions = async () => { const { rowCount } = await pool.query(sql` delete from ${table} where ${fields.expiresAt} < now() - or (${fields.isSamlResponseSent} = true and ${fields.isOidcStateChecked} = true) `); - return rowCount; + if (rowCount < 1) { + throw new DeletionError(SamlApplicationSessions.table); + } }; + const deleteSessionById = async (id: string) => { + const { rowCount } = await pool.query(sql` + delete from ${table} + where ${fields.id} = ${id} + `); + + if (rowCount < 1) { + throw new DeletionError(SamlApplicationSessions.table); + } + }; + + const findSessionById = async (id: string) => + pool.maybeOne(sql` + select ${sql.join(Object.values(fields), sql`, `)} + from ${table} + where ${fields.id}=${id} + `); + const findSessionsByApplicationId = async (applicationId: string) => pool.any(sql` select ${sql.join(Object.values(fields), sql`, `)} @@ -32,35 +65,13 @@ export const createSamlApplicationSessionQueries = (pool: CommonQueryMethods) => where ${fields.applicationId}=${applicationId} `); - const findAvailableSessionByAppIdAndState = async (applicationId: string, state: string) => - pool.one(sql` - select ${sql.join(Object.values(fields), sql`, `)} - from ${table} - where ${fields.applicationId}=${applicationId} - and ${fields.oidcState}=${state} and ${fields.isOidcStateChecked} = false and ${ - fields.expiresAt - } > now() - `); - - const findAvailableSessionByAppIdAndSamlRequestId = async ( - applicationId: string, - samlRequestId: string - ) => - pool.one(sql` - select ${sql.join(Object.values(fields), sql`, `)} - from ${table} - where ${fields.applicationId}=${applicationId} - and ${fields.samlRequestId}=${samlRequestId} and ${fields.isSamlResponseSent} = false and ${ - fields.expiresAt - } > now() - `); - return { insertSession, updateSession, - deleteExpiredOrFullyUsedSessions, + removeSessionOidcStateById, + deleteExpiredSessions, + deleteSessionById, + findSessionById, findSessionsByApplicationId, - findAvailableSessionByAppIdAndState, - findAvailableSessionByAppIdAndSamlRequestId, }; }; diff --git a/packages/schemas/alterations/next-1735012422-add-saml-application-sessions-table.ts b/packages/schemas/alterations/next-1735012422-add-saml-application-sessions-table.ts index c7a07ea3b..80c789860 100644 --- a/packages/schemas/alterations/next-1735012422-add-saml-application-sessions-table.ts +++ b/packages/schemas/alterations/next-1735012422-add-saml-application-sessions-table.ts @@ -13,23 +13,16 @@ const alteration: AlterationScript = { id varchar(32) not null, application_id varchar(21) not null references applications (id) on update cascade on delete cascade, - saml_request_id varchar(128), + saml_request_id varchar(128) not null, oidc_state varchar(32), - is_oidc_state_checked boolean not null default false, - is_saml_response_sent boolean not null default false, relay_state varchar(256), - auth_request_info jsonb not null, + raw_auth_request text not null, created_at timestamptz not null default(now()), expires_at timestamptz not null, primary key (tenant_id, id), constraint saml_application_sessions__application_type check (check_application_type(application_id, 'SAML')) ); - - create unique index saml_application_sessions__oidc_state - on saml_application_sessions (tenant_id, oidc_state); - create unique index saml_application_sessions__saml_request_id - on saml_application_sessions (tenant_id, saml_request_id); `); await applyTableRls(pool, 'saml_application_sessions'); }, diff --git a/packages/schemas/tables/saml_application_sessions.sql b/packages/schemas/tables/saml_application_sessions.sql index 344197ffe..e3f97dd38 100644 --- a/packages/schemas/tables/saml_application_sessions.sql +++ b/packages/schemas/tables/saml_application_sessions.sql @@ -8,25 +8,16 @@ create table saml_application_sessions ( application_id varchar(21) not null references applications (id) on update cascade on delete cascade, /** The identifier of the SAML SSO auth request ID, SAML request ID is pretty long. */ - saml_request_id varchar(128), + saml_request_id varchar(128) not null, /** The identifier of the OIDC auth request state. */ oidc_state varchar(32), - /** When checking the OIDC auth state, we should have this flag to prevent replay attack. */ - is_oidc_state_checked boolean not null default false, - /** When sending the SAML authn response, we should have this flag to prevent replay attack. */ - is_saml_response_sent boolean not null default false, /** The relay state of the SAML auth request. */ relay_state varchar(256), - /** The request info of the SAML auth request. */ - auth_request_info jsonb /* @use AuthRequestInfo */ not null, + /** The raw request of the SAML auth request. */ + raw_auth_request text not null, created_at timestamptz not null default(now()), expires_at timestamptz not null, primary key (tenant_id, id), constraint saml_application_sessions__application_type check (check_application_type(application_id, 'SAML')) ); - -create unique index saml_application_sessions__oidc_state - on saml_application_sessions (tenant_id, oidc_state); -create unique index saml_application_sessions__saml_request_id - on saml_application_sessions (tenant_id, saml_request_id);