How Jenkins Handles User Authentication with SecurityRealm Implementations

Jenkins delegates the entire authentication workflow to a pluggable SecurityRealm that returns Spring Security components and installs a servlet filter chain to process every login request.

The Jenkins open-source project (jenkinsci/jenkins) provides a flexible security architecture centered on the hudson.security.SecurityRealm class. This abstraction allows Jenkins to integrate with external identity providers such as LDAP, Active Directory, or custom user stores. Understanding how Jenkins SecurityRealm implementations work is essential for customizing authentication flows or developing custom security plugins.

The SecurityRealm Contract

The core class hudson.security.SecurityRealm defines the contract for all authentication in Jenkins【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L25-L53】. Rather than implementing authentication logic directly, Jenkins asks the active SecurityRealm to provide the necessary Spring Security objects and filter configurations. This design allows administrators to swap authentication mechanisms without modifying Jenkins core code.

The Three Core Components

Every SecurityRealm implementation must provide three tightly‑coupled pieces that work together to secure the application.

1. Security Components

The createSecurityComponents() method returns a SecurityComponents object containing the authentication stack【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L73-L80】. This tuple includes:

  • manager2 – An AuthenticationManager that validates credential pairs (username/password)
  • userDetails2 – A UserDetailsService that loads user objects from external stores
  • rememberMe2 – A RememberMeServices implementation for persistent login cookies

2. The Filter Chain

Jenkins builds a servlet filter chain via createFilter() and createFilterImpl() to intercept HTTP requests【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L126-L134】【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L45-L67】. The critical filters installed by default include:

  • AuthenticationProcessingFilter2 – Processes form submissions to j_spring_security_check and extracts credentials for the AuthenticationManager
  • RememberMeAuthenticationFilter – Restores sessions from remember‑me cookies
  • AnonymousAuthenticationFilter – Supplies the built‑in "anonymous" identity for unauthenticated requests
  • ExceptionTranslationFilter – Catches security exceptions and redirects to the login page

3. Credential Lookup

When the filter chain needs to resolve a username into a full user object, it invokes loadUserByUsername2(String)【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L56-L66】. The default implementation delegates to the UserDetailsService inside the SecurityComponents. Custom realms can override this method to provide specialized lookup logic, such as caching or database queries.

The Authentication Flow

A typical login request flows through the Jenkins SecurityRealm implementation in seven distinct steps:

  1. Login Submission – The browser submits credentials to the URL returned by getAuthenticationGatewayUrl() (defaulting to j_spring_security_check)【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L29-L34】
  2. Filter Interception – AuthenticationProcessingFilter2 extracts the username and password from the HTTP request
  3. Credential Validation – The filter passes credentials to the AuthenticationManager (manager2), which validates them against the external store (LDAP, Active Directory, etc.)
  4. User Loading – Upon successful validation, the UserDetailsService loads the complete user profile via loadUserByUsername2
  5. Context Population – The authenticated Authentication object is stored in the Spring Security SecurityContextHolder
  6. Remember‑Me Processing – If the login form included the remember‑me checkbox, the RememberMeServices creates a signed cookie for future sessions
  7. Redirect – The AuthenticationSuccessHandler redirects the user to the URL specified in the from query parameter, or to the root context if none exists【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L75-L78】

Logout Handling

The doLogout() method in SecurityRealm handles session termination【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L46-L56】. This method invalidates the current HTTP session, removes any JSESSIONID cookies, clears the remember‑me cookie, and redirects to getPostLogOutUrl2(). Custom realms can override this behavior to perform additional cleanup, such as revoking OAuth tokens or logging audit events.

Practical Implementation Examples

Minimal Custom SecurityRealm

The following example implements a basic in‑memory authentication store by overriding only createSecurityComponents():

package org.example.jenkins;

import hudson.Extension;
import hudson.security.SecurityRealm;
import hudson.security.SecurityComponents;
import org.kohsuke.stapler.DataBoundConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.User;
import java.util.Map;

public class InMemorySecurityRealm extends SecurityRealm {

    private final Map<String, String> users;

    @DataBoundConstructor
    public InMemorySecurityRealm(Map<String, String> users) {
        this.users = users;
    }

    @Override
    public SecurityComponents createSecurityComponents() {
        AuthenticationManager am = authentication -> {
            String name = authentication.getName();
            String pwd = (String) authentication.getCredentials();
            if (users.containsKey(name) && users.get(name).equals(pwd)) {
                authentication.setAuthenticated(true);
                return authentication;
            }
            throw new BadCredentialsException("Invalid user");
        };
        
        UserDetailsService uds = username -> {
            if (!users.containsKey(username)) {
                throw new UsernameNotFoundException(username);
            }
            return User.withUsername(username)
                       .password(users.get(username))
                       .authorities("authenticated")
                       .build();
        };
        
        return new SecurityComponents(am, uds);
    }
}

Key implementation note: By providing the AuthenticationManager and UserDetailsService, the default filter chain (createFilterImpl) automatically handles form processing and session management.

Disabling Authentication

To run Jenkins without security (useful for testing), set the None realm:

Jenkins.get().setSecurityRealm(SecurityRealm.NO_AUTHENTICATION);

The None implementation returns an empty filter chain (ChainedServletFilter2 with no filters), effectively bypassing all authentication checks【https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/security/SecurityRealm.java#L76-L78】.

Customizing the Login URL

Override getLoginUrl() to redirect unauthenticated users to a custom login page:

public class LegacyRealm extends SecurityRealm {
    @Override
    public String getLoginUrl() {
        return "myCustomLogin";  // Maps to /myCustomLogin
    }
}

The ExceptionTranslationFilter uses this value when redirecting unauthorized requests.

Key Source Files

File Path Purpose
core/src/main/java/hudson/security/SecurityRealm.java Core contract and default filter chain implementation
core/src/main/java/hudson/security/LegacySecurityRealm.java Backward‑compatible realm delegating to servlet container authentication
core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java Default mutable user store with internal account management
core/src/main/java/hudson/security/AbstractPasswordBasedSecurityRealm.java Helper base class for password‑based realms (LDAP, etc.)
test/src/test/java/hudson/security/SecurityRealmTest.java Unit tests validating filter chain and login flows

Summary

  • SecurityRealm is the central abstraction that connects Jenkins to external identity providers via the hudson.security package.
  • Implementations must provide SecurityComponents (AuthenticationManager, UserDetailsService, RememberMeServices) through createSecurityComponents().
  • The filter chain (createFilterImpl()) processes every request using AuthenticationProcessingFilter2 to handle form logins and ExceptionTranslationFilter to manage access denials.
  • User lookup flows through loadUserByUsername2(), which delegates to the realm's UserDetailsService.
  • Logout is handled by doLogout(), which clears sessions and cookies before redirecting.

Frequently Asked Questions

What is the difference between SecurityRealm and AuthorizationStrategy in Jenkins?

SecurityRealm handles authentication (verifying who you are), while AuthorizationStrategy handles authorization (determining what you can do). The SecurityRealm validates credentials and populates the user context, whereas the AuthorizationStrategy checks permissions against that context on every resource access. These are configured separately in the Jenkins "Configure Global Security" page.

How do I implement a custom SecurityRealm for Jenkins?

Extend hudson.security.SecurityRealm and override createSecurityComponents() to return an AuthenticationManager and UserDetailsService. If you need custom login pages, override getLoginUrl(). Package your implementation as a Jenkins plugin with the @Extension annotation so Jenkins can discover it. Refer to AbstractPasswordBasedSecurityRealm if your realm only needs to verify passwords against an external store.

What happens when authentication fails in Jenkins?

When the AuthenticationManager rejects credentials, it throws an AuthenticationException. The ExceptionTranslationFilter catches this exception and redirects the user to the login URL returned by getLoginUrl(), typically displaying an error message. The AuthenticationProcessingFilter2 stores the failure details in the session for the login page to render.

How does the Remember Me feature work in Jenkins SecurityRealm?

When a user checks "Remember me on this computer," the AuthenticationProcessingFilter2 notifies the RememberMeServices (provided in SecurityComponents) upon successful login. The service generates a signed cookie containing the username and stores it in the browser. On subsequent visits, the RememberMeAuthenticationFilter detects this cookie, validates the signature, and reconstructs the authentication object without requiring the user to re-enter credentials. The cookie is cleared when doLogout() is called.

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 →