* fix(oidc): bind logout URLs to the current session (forced-logout CSRF)
Logout URLs were signed only over the redirect target and a timestamp, so any
valid, unexpired logout URL would clear whoever's cookies followed it. The
logout signature now also covers the caller's sqlpage_auth cookie, so a logout
URL only logs out the session it was issued for. Generation and verification
select the same cookie (the last of any duplicates, matching how RequestInfo
merges them) so the check stays consistent.
* style: run cargo fmt on the logout cookie test
Bump sqlparser from 0.61.0 to 0.62.0, hmac from 0.12 to 0.13, and sha2 from 0.10 to 0.11. Refresh Cargo.lock and remove SQLPage's direct password-hash dependency by using argon2's re-exported password_hash API.
SQLPage parses every .sql file before execution, rewrites SQLPage variables/functions through the sqlparser AST, and serializes the AST back to SQL. The sqlparser bump therefore changes which SQL text reaches the database.
SQLPage-visible sqlparser 0.62 changes for supported dialects:
- PostgreSQL: SQLPage can now parse and pass through LOCK TABLE; PRIMARY KEY/UNIQUE USING INDEX; parenthesized CREATE TABLE ... (LIKE ... INCLUDING/EXCLUDING DEFAULTS); COMMENT ON for additional object types; two-argument TRIM(string, characters); INTERVAL as an unquoted identifier; SETOF return types; ALTER FUNCTION/ALTER AGGREGATE; xml '...' typed strings; COLLATE after compound identifiers; LATERAL function calls WITH ORDINALITY; and pg_hint_plan-style SELECT optimizer hints in leading comments.
- MySQL: SQLPage can now parse and pass through KEY column options in CREATE TABLE and ORDER BY on single-table UPDATE. Incomplete DIV expressions now become SQLPage parser errors instead of panicking the parser.
- SQLite: incomplete REGEXP/MATCH expressions now become SQLPage parser errors instead of panicking the parser; two-argument TRIM(string, characters) is accepted.
- DuckDB: two-argument TRIM(string, characters) is accepted.
- MSSQL: SQLPage can now parse and pass through THROW, WAITFOR, BEGIN/COMMIT/ROLLBACK TRAN, EXEC(@sql) dynamic SQL, OUTPUT clauses on INSERT/UPDATE/DELETE, and dollar-prefixed money constants. Statement-starting keywords such as DECLARE, EXEC, INSERT, UPDATE, DELETE, CREATE, ALTER, RETURN, THROW, RAISERROR, and MERGE are no longer consumed as implicit aliases after SELECT items or table factors, so multi-statement T-SQL batches are less likely to be rejected by SQLPage's pre-parser.
- Oracle: SQLPage can now parse and pass through table aliases on INSERT targets and INSERT INTO (<sub-query>) forms.
- Snowflake: SQLPage can now parse and pass through multi-table INSERT, lambda functions, wildcard EXCLUDE fixes, stage-name/COPY parsing fixes, CHANGES clauses, COPY GRANTS, STORAGE LIFECYCLE POLICY, and text data type modifiers.
- Generic ODBC dialect: SQLPage now accepts the same new GenericDialect syntax as sqlparser 0.62, including UPDATE ... ORDER BY, KEY column options, comma TRIM, CTEs without AS, multi-column SELECT aliases, and xml typed strings. It no longer accepts lambda expressions in GenericDialect; databases detected as Snowflake still use SnowflakeDialect and keep lambda parsing.
SQLPage's special CSV upload handling is unchanged: it still intercepts COPY FROM file targets only. SQLPage's HMAC and password-hash outputs are intended to be unchanged; only imports/API wiring changed for the RustCrypto crates.
Lockfile-only runtime dependency updates include rustls 0.23.37 -> 0.23.40, rustls-pki-types 1.14.0 -> 1.14.1, webpki-roots 1.0.6 -> 1.0.7, aws-lc-rs 1.16.2 -> 1.17.0, tokio 1.51.1 -> 1.52.3, and config 0.15.22 -> 0.15.23. No SQLPage code changed for these; the user-visible surface is the upstream TLS/runtime/config bugfix behavior of those crates.
Validation before amend: cargo fmt --all; cargo clippy --all-targets --all-features -- -D warnings; cargo test.
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been cancelled
Add a discovery request counter to FakeOidcProvider and assert it
increments after the background refresh completes. Remove unused
set_discovery_delay method.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace std::time::Instant with tokio::time::Instant in OidcSnapshot so
that tokio::time::pause()/advance() controls elapsed time in tests.
Remove force_expire() — tests advance time past MAX_REFRESH_INTERVAL
instead. Simplify slow discovery test from ~70 to ~30 lines.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- OIDC provider metadata refreshes now run in a background task via
spawn_local, never blocking incoming HTTP requests.
- Multiple concurrent refresh triggers are deduplicated via an AtomicBool.
- The write lock on the OIDC client is only held briefly to swap data,
not during the upstream HTTP call.
- Add a body-read timeout to OIDC HTTP requests to prevent hangs when
the provider stalls after sending headers.
- Add tests for both scenarios: slow discovery and slow token endpoint.
Fixes https://github.com/sqlpage/SQLPage/issues/1231
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* add timeout to OIDC HTTP response body read
A stalled OIDC provider that sends HTTP headers but never completes the
body would cause response.body().await to hang forever, freezing the
entire SQLPage process. Add a 5-second timeout on the body stream read
using awc's ClientResponse::timeout().
partially Fixes#1231
* simplify test comment
* simplify test: use token_endpoint_delay instead of Notify gate
* simplify test: use tokio time pause + auto-advance instead of select
* use spawn_local + advance instead of select to detect hang
* use Notify sync point instead of yield loop for deterministic test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* simplify test: replace Notify+yields with sleep+time-advance
Remove the Notify synchronization and yield_now() calls. Instead,
use a small real-time sleep for TCP to complete, then pause+advance
tokio time. Assert the actual response status instead of is_finished().
* fix clippy: remove unnecessary mut on response
* fix(oidc): respect site_prefix in OIDC redirect and logout URLs
This change ensures that when `site_prefix` is configured, the OIDC redirect URI and logout URI include this prefix.
Previously, `site_prefix` was ignored, causing OIDC callbacks to fail when the application was served under a sub-path.
- Added `site_prefix` to `OidcConfig`.
- Updated `make_oidc_client` to prepend `site_prefix` to the redirect URI.
- Updated `handle_request` to match paths with `site_prefix` included.
- Updated `validate_redirect_url` to respect the prefix when verifying redirect targets.
- Added a regression test `test_oidc_with_site_prefix`.
* Refactor: Update dependencies and remove unused crates
This commit updates several dependencies to their latest versions and removes unused crates to streamline the project.
Co-authored-by: contact <contact@ophir.dev>
* removed unused config
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit refactors the OIDC tests to use a more robust fake OIDC provider and improves the logout URL generation to correctly handle the scheme.
Fixes https://github.com/sqlpage/SQLPage/issues/1174
cargo test was failing with too many open files because each test server
spawned a worker per CPU, quickly exhausting file descriptors when tests ran
in parallel. Set test servers to one worker so they use a bounded number of
sockets/threads, avoiding fd exhaustion and letting OIDC and migration tests
start reliably.
This commit introduces a macro for handling requests with cookies, simplifying the OIDC test flow. It also removes redundant session management functions, enhancing code clarity and maintainability. The setup function for OIDC tests is updated to improve readability and streamline the initialization process.
Refactor OIDC login simulation by extracting query parameter logic into a separate function and renaming the callback function for clarity. This improves code readability and maintainability.