How to Configure OAuth2 Authentication in Stirling-PDF: Enterprise SSO Guide

Enable OAuth2 in Stirling-PDF by setting security.oauth2.enabled: true in settings.yml, configuring provider-specific client credentials, and ensuring the redirect URI {baseUrl}/login/oauth2/code/{registrationId} is registered with your identity provider.

Stirling-PDF supports OAuth2 Single Sign-On (SSO) through external identity providers such as Google, GitHub, Keycloak, or any generic OpenID Connect server. This guide explains how to configure OAuth2 authentication in Stirling-PDF based on the actual implementation in the Stirling-Tools/Stirling-PDF repository.

Understanding the OAuth2 Architecture in Stirling-PDF

The OAuth2 implementation consists of three distinct layers that handle configuration, security registration, and UI rendering.

Configuration Layer: ApplicationProperties.java

All OAuth2 settings are loaded from settings.yml into the Security.OAUTH2 inner class inside [ApplicationProperties.java](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java). This POJO maps YAML properties such as security.oauth2.enabled, client.google.clientId, and useAsUsername to Java objects used by the security layer.

Security Layer: OAuth2Configuration.java

The [OAuth2Configuration.java](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java) class constructs ClientRegistration objects for each enabled provider and registers them with Spring Security’s InMemoryClientRegistrationRepository. The validateProvider() method ensures each configured provider has valid credentials before registration, while clientRegistrationRepository() exposes the repository bean to the Spring Security filter chain.

Frontend Layer: OAuthButtons.tsx

The React component [OAuthButtons.tsx](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/proprietary/routes/login/OAuthButtons.tsx) renders login buttons for each provider exposed by the backend API. Each button links to /oauth2/authorization/{registrationId}, triggering the standard Spring Security OAuth2 redirect flow.

Step-by-Step Configuration Guide

Enable OAuth2 Globally

Edit settings.yml to enable the OAuth2 module and define which user attribute to map as the internal username:

security:
  oauth2:
    enabled: true
    useAsUsername: email

The useAsUsername field accepts values such as email or preferred_username depending on your identity provider’s claims.

Configure Google OAuth2

Add the Google provider block under security.oauth2.client:

security:
  oauth2:
    client:
      google:
        clientId: ${GOOGLE_CLIENT_ID}
        clientSecret: ${GOOGLE_CLIENT_SECRET}
        scopes:
          - openid
          - profile
          - email

Configure GitHub OAuth2

GitHub uses OAuth rather than OIDC, requiring specific scopes for user data access:

security:
  oauth2:
    client:
      github:
        clientId: ${GITHUB_CLIENT_ID}
        clientSecret: ${GITHUB_CLIENT_SECRET}
        scopes:
          - read:user
          - user:email

Configure Generic OIDC (Keycloak Example)

For Keycloak or any standard OIDC provider, use the provider and issuer fields:

security:
  oauth2:
    provider: keycloak
    issuer: https://keycloak.example.com/realms/myrealm
    useAsUsername: preferred_username
    client:
      keycloak:
        clientId: ${KC_CLIENT_ID}
        clientSecret: ${KC_CLIENT_SECRET}
        scopes:
          - openid
          - profile
          - email

The provider value becomes the registrationId used in the redirect URI path.

Auto-Create Users on First Login

To automatically provision internal user accounts when new users authenticate via OAuth2:

security:
  oauth2:
    autoCreateUser: true

When false, only existing Stirling-PDF users can log in via OAuth2.

Restart and Verify

  1. Restart the application to trigger OAuth2Configuration.clientRegistrationRepository() validation
  2. Verify the redirect URI format {baseUrl}/login/oauth2/code/{registrationId} is registered with your identity provider (e.g., https://pdf.example.com/login/oauth2/code/google)
  3. Check that OAuthButtons.tsx renders buttons linking to /oauth2/authorization/{registrationId}

Complete Configuration Example


# settings.yml – Production-ready OAuth2 configuration

security:
  enableLogin: true
  oauth2:
    enabled: true
    useAsUsername: email
    autoCreateUser: true

    client:
      google:
        clientId: ${GOOGLE_CLIENT_ID}
        clientSecret: ${GOOGLE_CLIENT_SECRET}
        scopes:
          - openid
          - profile
          - email

      github:
        clientId: ${GITHUB_CLIENT_ID}
        clientSecret: ${GITHUB_CLIENT_SECRET}
        scopes:
          - read:user
          - user:email

    provider: keycloak
    issuer: https://keycloak.example.com/realms/production
    client:
      keycloak:
        clientId: ${KC_CLIENT_ID}
        clientSecret: ${KC_CLIENT_SECRET}
        scopes:
          - openid
          - profile
          - email

Environment variables (${...}) are resolved at runtime via Spring Boot’s relaxed binding, keeping secrets out of version control.

Key Source Files Reference

Troubleshooting Common OAuth2 Issues

No Login Buttons Appear

Symptom: The OAuth2 login buttons do not display on the login page. Cause: security.oauth2.enabled is false or the settings.yml file cannot be loaded from the path resolved by InstallationPathConfig.getSettingsPath(). Fix: Verify the YAML syntax and ensure oauth2.enabled: true is set under the security block.

"Invalid Client" or Redirect URI Mismatch Errors

Symptom: The identity provider returns an error about invalid clients or redirect URIs. Cause: The redirect URI is not registered in the provider’s OAuth2 console. Fix: Register the exact URI format used by OAuth2Configuration.REDIRECT_URI_PATH: {baseUrl}/login/oauth2/code/{registrationId}. For example, https://pdf.example.com/login/oauth2/code/google.

Login Succeeds but User Is Not Created

Symptom: Authentication succeeds at the provider, but Stirling-PDF shows an error or redirects back to login. Cause: The user does not exist in the local database and autoCreateUser is disabled. Fix: Set security.oauth2.autoCreateUser: true in settings.yml to automatically provision accounts, or pre-create the user via the admin interface.

Desktop Client Never Returns from Browser

Symptom: When using the Tauri desktop application, the OAuth flow hangs after browser authentication. Cause: The desktop OAuth callback is not being handled by TauriOAuthUtils.java. Fix: Ensure the desktop build includes the proprietary security module and that the OAuth redirect uses the custom tauri:// scheme configured in DesktopOAuthButtons.tsx.

Summary

  • Enable OAuth2 by setting security.oauth2.enabled: true in settings.yml to activate the Spring Security OAuth2 flow.
  • Configure providers under security.oauth2.client for Google, GitHub, or generic OIDC providers like Keycloak using issuer and provider fields.
  • Set redirect URIs to {baseUrl}/login/oauth2/code/{registrationId} in your identity provider console to match the path defined in OAuth2Configuration.java.
  • Enable auto-provisioning with autoCreateUser: true to allow new users to log in without manual account creation.
  • Reference implementation files such as ApplicationProperties.java, OAuth2Configuration.java, and OAuthButtons.tsx when debugging or extending functionality.

Frequently Asked Questions

What is the exact redirect URI format for Stirling-PDF OAuth2?

The redirect URI must follow the format {baseUrl}/login/oauth2/code/{registrationId}, where registrationId is the provider name configured in settings.yml (such as google, github, or your custom provider value). This path is defined as OAuth2Configuration.REDIRECT_URI_PATH in the Java source code. You must register this exact URI, including the correct base URL and provider ID, in your identity provider's OAuth2 console to avoid "redirect_uri mismatch" errors.

How do I enable automatic user creation for OAuth2 logins?

Set security.oauth2.autoCreateUser: true in your settings.yml configuration file. When this property is enabled, Stirling-PDF automatically creates a local user account upon first successful OAuth2 authentication, using the attribute specified in useAsUsername (typically email or preferred_username) as the internal username. If disabled, only existing users pre-created in the Stirling-PDF database can authenticate via OAuth2, and new users will be denied access.

Can I use multiple OAuth2 providers simultaneously?

Yes, Stirling-PDF supports concurrent configuration of multiple OAuth2 providers. You can define multiple clients under security.oauth2.client (such as google, github, and a custom keycloak entry) simultaneously. The OAuth2Configuration.java class iterates through all configured providers and registers each as a separate ClientRegistration in the InMemoryClientRegistrationRepository. The frontend component OAuthButtons.tsx dynamically renders a login button for each registered provider, allowing users to choose their preferred authentication method.

Why are the OAuth2 login buttons not appearing in the UI?

The OAuth2 login buttons are rendered by OAuthButtons.tsx only when the backend exposes OAuth2 providers through the API, which requires security.oauth2.enabled: true in settings.yml. If the buttons are missing, first verify that the configuration file is being loaded correctly from the path resolved by InstallationPathConfig.getSettingsPath(). Ensure the YAML syntax is valid and that at least one provider (such as client.google or client.github) is properly configured with valid credentials. If running the desktop Tauri client, ensure you are viewing DesktopOAuthButtons.tsx and that the proprietary security module containing TauriOAuthUtils.java is included in the build.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →