Skip to content

Conversation

@DarioGii
Copy link
Contributor

Main Issues Fixed:

  1. Tools Disabled on Initial Login (Required Page Refresh)

Problem: After successful login, all PDF tools appeared grayed out/disabled until the user refreshed the page.

Root Cause: Race condition where tools checked endpoint availability before JWT was stored in localStorage.

Fix:

  • Implemented optimistic defaults in useEndpointConfig - assumes endpoints are enabled when no JWT exists
  • Added JWT availability event system (jwt-available event) to notify components when authentication is ready
  • Tools now remain enabled during auth initialization instead of defaulting to disabled
  1. Session Lost on Page Refresh (Immediate Logout)

Problem: Users were immediately logged out when refreshing the page, losing their authenticated session.

Root Causes:

  • Spring Security form login was redirecting API calls to /login with 302 responses instead of returning JSON
  • /api/v1/auth/me endpoint was incorrectly in the permitAll list
  • JWT filter wasn't allowing /api/v1/config endpoints without authentication

Fixes:

  • Backend: Disabled form login in v2/JWT mode by adding && !v2Enabled condition to form login configuration
  • Backend: Removed /api/v1/auth/me from permitAll list - it now requires authentication
  • Backend: Added /api/v1/config to public endpoints in JWT filter
  • Backend: Configured proper exception handling for API endpoints to return JSON (401) instead of HTML redirects (302)
  1. Multiple Duplicate API Calls

Problem: After login, /app-config was called 5+ times, /endpoints-enabled and /me called multiple times, causing unnecessary network traffic.

Root Cause: Multiple React components each had their own instance of useAppConfig and useEndpointConfig hooks, each fetching data independently.

Fix:

  • Frontend: Created singleton AppConfigContext provider to ensure only one global config fetch
  • Frontend: Added global caching to useEndpointConfig with module-level cache variables
  • Frontend: Implemented fetch deduplication with fetchCount tracking and globalFetchedSets
  • Result: Reduced API calls from 5+ to 1-2 per endpoint (2 in dev due to React StrictMode)

Additional Improvements:

CORS Configuration

  • Added flexible CORS configuration matching SaaS pattern
  • Explicitly allows localhost development ports (3000, 5173, 5174, etc.)
  • No hardcoded URLs in application.properties

Security Handlers Integration

  • Added IP-based account locking without dependency on form login
  • Preserved audit logging with @Audited annotations

Key Code Changes:

Backend Files:

  • SecurityConfiguration.java - Disabled form login for v2, added CORS config
  • JwtAuthenticationFilter.java - Added /api/v1/config to public endpoints
  • JwtAuthenticationEntryPoint.java - Returns JSON for API requests

Frontend Files:

  • AppConfigContext.tsx - New singleton context for app configuration
  • useEndpointConfig.ts - Added global caching and deduplication
  • UseSession.tsx - Removed redundant config checking
  • Various hooks - Updated to use context providers instead of direct fetching
DarioGii and others added 10 commits October 29, 2025 12:23
This PR introduces JWT (JSON Web Token) authentication for Stirling-PDF,
allowing for stateless authentication capabilities alongside the
existing session-based authentication system.

### Key Features & Changes

  JWT Authentication System
- Core Service: JwtService.java - Token generation, validation, and
cookie management
- Authentication Filter: JwtAuthenticationFilter.java - Request
interceptor for JWT validation
- Key Management: KeyPersistenceService.java +
KeyPairCleanupService.java - RSA key rotation and persistence
  - Frontend: jwt-init.js - Client-side JWT handling and URL cleanup

  Security Integration
- SAML2: JwtSaml2AuthenticationRequestRepository.java - JWT-backed SAML
request storage
- OAuth2: Updated CustomAuthenticationSuccessHandler. java,
CustomOAuth2AuthenticationSuccessHandler.java &
CustomSaml2AuthenticationSuccessHandler.java for JWT integration
- Configuration: Enhanced SecurityConfiguration.java with JWT filter
chain

  Infrastructure
  - Caching: CacheConfig.java - Caffeine cache for JWT keys
  - Database: New JwtVerificationKey.java entity for key storage
- Error Handling: JwtAuthenticationEntryPoint.java for unauthorized
access

### Challenges Encountered

- Configured SecurityConfiguration to use either
`UsernamePasswordAuthenticationFilter` or `JWTAuthenticationFilter`
based on whether JWTs are enabled to prevent the former intercepting
requests while in stateless mode.
- Removed the `.defaultSuccessUrl("/")` from login configuration as its
inclusion was preventing overriding the use of the
`CustomAuthenticationSuccessHandler` and preventing proper
authentication flows.
---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [x] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [x] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [x] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [x] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
<img width="599" height="515" alt="Screenshot 2025-07-10 at 13 35 56"
src="https://github.com/user-attachments/assets/4126b752-ad0d-4ffa-b295-6714c43381e1"
/>

<img width="392" height="376" alt="Screenshot 2025-07-10 at 13 36 10"
src="https://github.com/user-attachments/assets/c681bc43-68ff-4934-8245-d544e2ad7b9c"
/>

<img width="1870" height="986" alt="eb750e8c3954fc47b2dd2e6e76ddb7d5"
src="https://github.com/user-attachments/assets/fca9b23d-b0b6-4884-8a26-98a441b641ef"
/>

<img width="1299" height="702" alt="Screenshot 2025-07-10 at 13 30 57"
src="https://github.com/user-attachments/assets/9415d8bf-fac4-4d38-8c3a-985d043d1076"
/>

### Testing (if applicable)

- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ludy <Ludy87@users.noreply.github.com>
Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
Co-authored-by: Ethan <ethan@MacBook-Pro.local>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
# Conflicts:
#	.claude/settings.local.json
#	app/common/src/main/java/stirling/software/common/configuration/AppConfig.java
#	app/core/src/main/resources/static/js/fetch-utils.js
#	app/core/src/main/resources/static/js/jwt-init.js
#	app/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java
#	app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java
Auto-generated by [create-pull-request][1] with **stirlingbot**

[1]: https://github.com/peter-evans/create-pull-request

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
# Conflicts:
#	frontend/src/core/contexts/AppConfigContext.tsx
#	frontend/src/core/hooks/useEndpointConfig.ts
Adds granular privacy controls for analytics - splits single
enableAnalytics toggle into separate PostHog and Scarf controls with
improved admin
  UX.

  Backend Changes

  Configuration (ApplicationProperties.java)
  - Added enablePosthog and enableScarf boolean fields
- New methods: isPosthogEnabled(), isScarfEnabled() (null = enabled when
analytics is on)

  Services
- PostHogService: Now checks isPosthogEnabled() instead of
isAnalyticsEnabled()
  - ConfigController: Exposes new flags via API
- SettingsController: Changed endpoint from @RequestBody to
@RequestParam

  Frontend Changes

  Architecture
- Converted useAppConfig hook → AppConfigContext provider for global
access
  - Added refetch() method for config updates without reload

  New Features
1. AdminAnalyticsChoiceModal: First-launch modal when enableAnalytics
=== null
    - Enable/disable without editing YAML
    - Includes documentation link
  2. Scarf Tracking System: Modular utility with React hook wrapper
    - Respects config + per-service cookie consent
    - Works from any code location (React or vanilla JS)
3. Enhanced Cookie Consent: Per-service toggles (PostHog and Scarf
separate)

  Integration
  - App.tsx: Added AppConfigProvider + scarf initializer
  - HomePage.tsx: Shows admin modal when needed
  - index.tsx: PostHog opt-out by default, service-level consent

  Key Benefits

✅ Backward compatible (null defaults to enabled)
✅ Granular control per analytics service
✅ First-launch admin modal (no YAML editing)
✅ Privacy-focused with opt-out defaults
✅ API-based config updates

---------

Co-authored-by: Connor Yoh <connor@stirlingpdf.com>
# Conflicts:
#	frontend/src/App.tsx
#	frontend/src/contexts/AppConfigContext.tsx
Auto-generated by [create-pull-request][1] with **stirlingbot**

[1]: https://github.com/peter-evans/create-pull-request

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
@DarioGii DarioGii marked this pull request as ready for review October 30, 2025 11:18
@stirlingbot stirlingbot bot added Java Pull requests that update Java code v2 Issues or pull requests related to the v2 branch Security Security-related issues or pull requests API API-related issues or pull requests Test Testing-related issues or pull requests labels Oct 30, 2025
@dosubot dosubot bot added size:L This PR changes 100-499 lines ignoring generated files. Bugfix Pull requests that fix bugs labels Oct 30, 2025
@stirlingbot stirlingbot bot removed the Bugfix Pull requests that fix bugs label Oct 30, 2025
@dosubot dosubot bot added size:XL This PR changes 500-999 lines ignoring generated files. and removed size:L This PR changes 100-499 lines ignoring generated files. labels Oct 31, 2025
@stirlingbot stirlingbot bot added the Back End Issues related to back-end development label Oct 31, 2025
@stirlingbot
Copy link
Contributor

stirlingbot bot commented Oct 31, 2025

🚀 V2 Auto-Deployment Complete!

Your V2 PR with the new frontend/backend split architecture has been deployed!

🔗 Direct Test URL (non-SSL) http://185.252.234.121:4779

🔐 Secure HTTPS URL: https://4779.ssl.stirlingpdf.cloud

This deployment will be automatically cleaned up when the PR is closed.

🔄 Auto-deployed because PR title or branch name contains V2/version2/React keywords.

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

Labels

API API-related issues or pull requests Back End Issues related to back-end development Java Pull requests that update Java code Security Security-related issues or pull requests size:XL This PR changes 500-999 lines ignoring generated files. Test Testing-related issues or pull requests v2 Issues or pull requests related to the v2 branch

4 participants