Skip to main content

Overview

Faction supports OAuth 2.0 and OpenID Connect (OIDC) authentication, enabling single sign-on (SSO) with popular identity providers. This integration is built on the PAC4J framework and supports both OIDC and SAML 2.0 protocols.

Supported Providers

Faction’s OAuth implementation supports any OIDC-compliant identity provider:

Azure AD / Entra ID

Microsoft’s cloud identity platform

Okta

Enterprise identity management

Google Workspace

Google’s identity provider

Keycloak

Open source identity and access management

Auth0

Authentication and authorization platform

Custom OIDC

Any OIDC-compliant provider

Configuration

Environment Variables

Faction requires the following environment variable for OAuth callbacks:
FACTION_OAUTH_CALLBACK=https://your-faction-instance.com
The callback URL must be accessible from your identity provider and should use HTTPS in production.

OIDC Configuration

Configure OAuth 2.0 / OIDC in Faction’s system settings:
ssoEnabled: true
oauthClientId: your-client-id
oauthClientSecret: your-client-secret
oauthDiscoveryURI: https://provider.com/.well-known/openid-configuration

Parameter Descriptions

ParameterDescriptionRequired
ssoEnabledEnable/disable SSO authenticationYes
oauthClientIdClient ID from your identity providerYes
oauthClientSecretClient secret (encrypted in database)Yes
oauthDiscoveryURIOIDC discovery endpoint URLYes

Provider-Specific Setup

Azure AD / Entra ID

  1. Register Application in Azure Portal:
    • Navigate to Azure Active Directory > App registrations
    • Click New registration
    • Set name to “Faction”
    • Set redirect URI: https://your-faction-instance.com/oauth/callback
  2. Configure Application:
    • Note the Application (client) ID
    • Create a client secret in Certificates & secrets
    • Note the secret value (shown only once)
  3. Faction Configuration:
    ssoEnabled: true
    oauthClientId: <application-client-id>
    oauthClientSecret: <client-secret-value>
    oauthDiscoveryURI: https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration
    

Google Workspace

  1. Create OAuth 2.0 Client in Google Cloud Console:
    • Navigate to APIs & Services > Credentials
    • Click Create Credentials > OAuth client ID
    • Application type: Web application
    • Authorized redirect URIs: https://your-faction-instance.com/oauth/callback
  2. Faction Configuration:
    ssoEnabled: true
    oauthClientId: <client-id>.apps.googleusercontent.com
    oauthClientSecret: <client-secret>
    oauthDiscoveryURI: https://accounts.google.com/.well-known/openid-configuration
    

Okta

  1. Create OIDC Application in Okta Admin Console:
    • Navigate to Applications > Create App Integration
    • Sign-in method: OIDC
    • Application type: Web Application
    • Sign-in redirect URIs: https://your-faction-instance.com/oauth/callback
  2. Faction Configuration:
    ssoEnabled: true
    oauthClientId: <okta-client-id>
    oauthClientSecret: <okta-client-secret>
    oauthDiscoveryURI: https://<your-okta-domain>/.well-known/openid-configuration
    

Keycloak

  1. Create Client in Keycloak Admin Console:
    • Navigate to your realm > Clients > Create
    • Client ID: faction
    • Access Type: confidential
    • Valid Redirect URIs: https://your-faction-instance.com/oauth/callback
  2. Faction Configuration:
    ssoEnabled: true
    oauthClientId: faction
    oauthClientSecret: <client-secret-from-credentials-tab>
    oauthDiscoveryURI: https://<keycloak-server>/realms/<realm-name>/.well-known/openid-configuration
    

Callback URLs

Faction uses two callback endpoints for OAuth authentication:
  • OIDC Callback: https://your-faction-instance.com/oauth/callback
  • SAML2 Callback: https://your-faction-instance.com/saml2/callback
Both callbacks are automatically configured based on the FACTION_OAUTH_CALLBACK environment variable.

User Provisioning

Automatic Account Creation

When a user authenticates via OAuth for the first time, Faction automatically creates their account using claims from the ID token:
ClaimFaction FieldFallback
email / EmailAddressEmailRequired
given_nameFirst Name
family_nameLast Name
nameDisplay Name

Email Matching

Faction uses case-insensitive email matching to link OAuth accounts with existing users. If a user with the same email already exists, they’ll be authenticated into that account.

Claim Mapping

The OAuth implementation extracts email addresses from multiple claim formats:
// Standard OIDC claim
profile.getAttribute("email")

// Azure AD claim
profile.getAttribute("EmailAddress")

// SAML assertion claim
profile.getAttribute("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")
Relevant source code: src/com/fuse/utils/AccessControl.java:75

Implementation Details

PAC4J Configuration

Faction uses the PAC4J security framework with the following configuration:
// OIDC Configuration
config.setClientId(oauthClientId)
config.setSecret(oauthClientSecret)
config.setDiscoveryURI(oauthDiscoveryURI)
config.setUseNonce(true)
config.setPreferredJwsAlgorithm(JWSAlgorithm.RS256)

Dependencies

Faction includes the following OAuth-related dependencies (from pom.xml):
<dependency>
    <groupId>org.pac4j</groupId>
    <artifactId>jee-pac4j</artifactId>
    <version>5.0.0</version>
</dependency>
<dependency>
    <groupId>org.pac4j</groupId>
    <artifactId>pac4j-oidc</artifactId>
    <version>4.5.7</version>
</dependency>
<dependency>
    <groupId>org.pac4j</groupId>
    <artifactId>pac4j-saml</artifactId>
    <version>4.5.7</version>
</dependency>
Relevant source code:
  • src/com/fuse/authentication/oauth/SecurityConfigFactory.java
  • src/com/fuse/authentication/oauth/OIDCCallbackFilterWrapper.java
  • src/com/fuse/dao/SystemSettings.java:586-637

Testing Configuration

  1. Enable SSO in Faction settings
  2. Save configuration with your provider details
  3. Log out of Faction
  4. Click Sign in with SSO on the login page
  5. You should be redirected to your identity provider
  6. After authentication, you’ll be redirected back to Faction

Troubleshooting

  • Verify the redirect URI in your identity provider matches exactly: https://your-faction-instance.com/oauth/callback
  • Ensure the FACTION_OAUTH_CALLBACK environment variable is set correctly
  • Check for trailing slashes (should not be included)
  • Verify the client ID is correct
  • Ensure the client secret hasn’t expired
  • Check that the client secret is entered exactly as shown (no extra spaces)
  • Client secrets are encrypted in the database using Faction’s encryption utilities
  • Verify the discovery URI is correct and accessible
  • Test the endpoint manually: curl https://provider.com/.well-known/openid-configuration
  • Ensure Faction can reach the identity provider (check firewall rules)
  • Verify your identity provider includes the email claim in ID tokens
  • Check your provider’s scope configuration (should include “email” or “profile”)
  • Review Faction logs for the actual claims received
  • Ensure the user’s email is populated in your identity provider
  • Check that the email claim is present and valid
  • Verify Faction has database write permissions
  • Review application logs for error messages
  • Ensure the email format is valid

Security Considerations

Use HTTPS

Always use HTTPS for the callback URL in production. OAuth flows require secure communication.

Rotate Secrets

Regularly rotate client secrets and update them in both your identity provider and Faction.

Validate Claims

Faction validates the email claim before creating accounts. Ensure your provider includes verified email claims.

Monitor Access

Review OAuth authentication logs to detect unauthorized access attempts.

Advanced Configuration

Custom Parameters

Faction’s OIDC configuration supports custom parameters:
config.addCustomParam("display", "popup")
config.addCustomParam("prompt", "select_account")
Modify src/com/fuse/dao/SystemSettings.java:633-634 to add additional custom parameters.

Session Management

The OAuth callback filter is configured to:
  • Renew sessions after authentication (setRenewSession(true))
  • Support multiple authentication profiles (setMultiProfile(true))

Role Assignment

All OAuth-authenticated users are assigned the ROLE_USER role by default:
oidcClient.setAuthorizationGenerator((ctx, profile) -> {
    profile.addRole("ROLE_USER");
    return Optional.ofNullable(profile);
});

Build docs developers (and LLMs) love