Skip to content

12178 session cookie CSRF protections#12188

Open
ErykKul wants to merge 18 commits intodevelopfrom
12178_CSRF_session_cookie_CSRF_protections
Open

12178 session cookie CSRF protections#12188
ErykKul wants to merge 18 commits intodevelopfrom
12178_CSRF_session_cookie_CSRF_protections

Conversation

@ErykKul
Copy link
Collaborator

@ErykKul ErykKul commented Feb 27, 2026

What this PR does / why we need it:
This PR adds an opt-in hardening layer for API session-cookie auth (JSESSIONID) so JSF/SAML-style deployments can use session auth with stronger CSRF protections, without breaking existing token-based API clients.

This is one of the steps toward enabling SPA component reuse inside the classic JSF UI — see the broader plan in dataverse-frontend#468.

Implemented changes:

  • Adds a new feature flag: dataverse.feature.api-session-auth-hardening (FeatureFlags.API_SESSION_AUTH_HARDENING).
  • Adds request auth-mechanism tagging in API auth flow (apiKey, workflowKey, signedUrl, bearerToken, sessionCookie, none) via CompoundAuthMechanism.
  • Updates SessionCookieAuthMechanism to return only authenticated session users (guest session no longer tagged as session-cookie auth).
  • Adds per-session API CSRF token lifecycle in DataverseSession (getOrCreateApiCsrfToken, matchesApiCsrfToken, clearApiCsrfToken).
  • Adds GET /api/users/:csrf-token (auth required) for session-cookie clients to fetch CSRF token.
  • Adds hardening enforcement in AuthFilter (only when hardening flag is enabled and auth mechanism is sessionCookie):
    • Requires Origin/Referer + X-Dataverse-CSRF-Token for every session-cookie API request, regardless of HTTP method or path.
    • The rule is simple and uniform: if the request was authenticated via session cookie, it must include a valid same-origin Origin or Referer header and a valid CSRF token.
    • The CSRF token bootstrap endpoint (GET /api/users/:csrf-token) is exempt from the CSRF header check (but still requires same-origin validation).
  • Keeps behavior unchanged when hardening flag is off.
  • Adds a warning that enabling api-session-auth without api-session-auth-hardening exposes the installation to CSRF risks.

Which issue(s) this PR closes:

Special notes for your reviewer:

  • Scope is intentionally hardening-only and feature-flagged; default behavior is unchanged.
  • The hardening rule is deliberately uniform across all HTTP methods and API paths. Even GET requests are checked because some GET endpoints have side effects (e.g., GET /api/datasets/{id}/uploadurls, GET /api/datasets/{id}/cleanStorage). Since session-cookie API auth is only used by same-origin SPA clients that always have the CSRF token, requiring it on every request is simpler and safer than maintaining an allowlist.
  • @since for the new flag is set to Dataverse 6.10.

Suggestions on how to test this:

  1. Run focused tests:
    • AuthFilterTest
    • UsersSessionCsrfTokenTest
    • DataverseSessionTest
    • SessionCookieAuthMechanismTest
    • CompoundAuthMechanismTest
  2. Manual verification with flags:
    • Enable dataverse.feature.api-session-auth=true
    • Enable dataverse.feature.api-session-auth-hardening=true
  3. Login through JSF (any supported IdP path: builtin/Shibboleth/OIDC/etc.), then:
    • GET /api/users/:csrf-token with session cookie and Origin header returns token.
    • Any API call with correct Origin + X-Dataverse-CSRF-Token succeeds.
    • Same call missing/invalid Origin or CSRF token returns 403.
    • API calls using API token, bearer token, signed URL, or workflow key are unaffected by hardening.

Does this PR introduce a user interface change? If mockups are available, please link/include them here:
No direct UI change.

Is there a release notes update needed for this change?:
Yes, included:

  • doc/release-notes/12178-session-cookie-api-hardening.md

Additional documentation:

  • Installation/config docs updated:
    • doc/sphinx-guides/source/installation/config.rst
  • Native API docs updated:
    • doc/sphinx-guides/source/api/native-api.rst

Security model note: session-cookie hardening vs bearer token

This PR does not claim session-cookie auth is identical to bearer auth, but with hardening enabled it reaches a comparable security posture for first-party browser calls.

  • Session-cookie auth (JSESSIONID) is normally vulnerable to CSRF because cookies are sent automatically by browsers.
  • This PR adds explicit anti-CSRF controls for session-cookie requests:
    • Strict Origin/Referer validation on every request
    • X-Dataverse-CSRF-Token validation on every request
  • Result: cross-site forged requests are blocked under the hardening flag.

Comparison to bearer:

  • Bearer is not auto-sent by the browser, so CSRF exposure is lower by default.
  • Session cookies with HttpOnly can reduce JS-level token exposure compared to bearer tokens stored in browser-accessible storage.
  • Both mechanisms remain vulnerable to credential theft (session hijack or token theft), so HTTPS, secure cookie/token handling, and XSS prevention are still required.

- Added CSRF token management to DataverseSession for session-cookie authentication.
- Introduced new feature flag `dataverse.feature.api-session-auth-hardening` to enable CSRF protections.
- Enhanced AuthFilter to validate CSRF tokens and request origins for state-changing API calls.
- Updated CompoundAuthMechanism to tag authentication mechanisms in requests.
- Created new endpoint `GET /api/users/:csrf-token` for clients to retrieve CSRF tokens.
- Added tests for new functionality and updated existing tests to cover new behavior.
- Documented changes in release notes for clarity on new security features.
@github-actions github-actions bot added the Type: Feature a feature request label Feb 27, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an opt-in “API session-cookie auth hardening” track to support JSESSIONID-based API usage with CSRF protections and endpoint guardrails, without changing default behavior when the flag is off.

Changes:

  • Adds auth-mechanism tagging to the API auth flow (apiKey, workflowKey, signedUrl, bearerToken, sessionCookie, none) and ensures guest sessions are not treated as session-cookie auth.
  • Implements session-scoped API CSRF token lifecycle in DataverseSession and introduces GET /api/users/:csrf-token to retrieve it (auth required).
  • Enforces hardening rules in AuthFilter (Origin/Referer + X-Dataverse-CSRF-Token for mutating requests, plus /api/access/* and mutating-GET guardrails) and adds focused tests/docs.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/test/java/edu/harvard/iq/dataverse/api/auth/SessionCookieAuthMechanismTest.java Adds coverage ensuring guest sessions don’t authenticate via session-cookie mechanism.
src/test/java/edu/harvard/iq/dataverse/api/auth/CompoundAuthMechanismTest.java Updates tests to assert auth-mechanism tagging behavior.
src/test/java/edu/harvard/iq/dataverse/api/auth/AuthFilterTest.java New tests for session-cookie hardening behavior (Origin/CSRF/access guardrails).
src/test/java/edu/harvard/iq/dataverse/DataverseSessionTest.java New tests for CSRF token creation/reuse/clear lifecycle.
src/main/java/edu/harvard/iq/dataverse/settings/FeatureFlags.java Adds API_SESSION_AUTH_HARDENING feature flag and updates related documentation.
src/main/java/edu/harvard/iq/dataverse/api/auth/SessionCookieAuthMechanism.java Ensures only authenticated (non-guest) session users are treated as session-cookie auth.
src/main/java/edu/harvard/iq/dataverse/api/auth/CompoundAuthMechanism.java Sets request auth-mechanism tag on ContainerRequestContext.
src/main/java/edu/harvard/iq/dataverse/api/auth/AuthFilter.java Implements session-cookie CSRF/origin enforcement + /api/access/* and mutating-GET guardrails behind the hardening flag.
src/main/java/edu/harvard/iq/dataverse/api/Users.java Adds GET /api/users/:csrf-token endpoint for session-cookie clients (hardening required).
src/main/java/edu/harvard/iq/dataverse/api/ApiConstants.java Adds constants for auth-mechanism tagging and CSRF header name.
src/main/java/edu/harvard/iq/dataverse/DataverseSession.java Adds per-session API CSRF token storage and clears it on user changes.
doc/sphinx-guides/source/installation/config.rst Documents new hardening flag and deployment guidance for cookie attributes.
doc/sphinx-guides/source/api/native-api.rst Documents CSRF token endpoint and usage for session-cookie clients.
doc/release-notes/12178-session-cookie-api-hardening.md Adds release note entry for the new hardening track.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

@coveralls
Copy link

coveralls commented Mar 18, 2026

Coverage Status

coverage: 24.909% (+0.07%) from 24.842%
when pulling 3333365 on 12178_CSRF_session_cookie_CSRF_protections
into d55acc6 on develop.

@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

ErykKul and others added 2 commits March 18, 2026 15:01
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

ErykKul and others added 3 commits March 18, 2026 16:50
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ErykKul and others added 2 commits March 18, 2026 17:07
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

3 similar comments
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@ErykKul ErykKul marked this pull request as ready for review March 18, 2026 16:18
@ErykKul ErykKul requested a review from qqmyers March 18, 2026 16:19
@ErykKul ErykKul moved this to Ready for Review ⏩ in IQSS Dataverse Project Mar 18, 2026
@github-actions

This comment has been minimized.

2 similar comments
@github-actions

This comment has been minimized.

@github-actions
Copy link

📦 Pushed preview images as

ghcr.io/gdcc/dataverse:12178-CSRF-session-cookie-CSRF-protections
ghcr.io/gdcc/configbaker:12178-CSRF-session-cookie-CSRF-protections

🚢 See on GHCR. Use by referencing with full name as printed above, mind the registry name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Feature a feature request

Projects

Status: Ready for Review ⏩

Development

Successfully merging this pull request may close these issues.

Feature Request: Session-Cookie API Hardening with CSRF Protections and Mutating-GET Guardrails

3 participants