# How Jenkins Handles User Authentication with SecurityRealm Implementations

> Learn how Jenkins handles user authentication using SecurityRealm implementations. Discover how Jenkins delegates authentication to pluggable SecurityRealms for secure login processing.

- Repository: [Jenkins/jenkins](https://github.com/jenkinsci/jenkins)
- Tags: internals
- Published: 2026-06-19

---

**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()`:

```java
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:

```java
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:

```java
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`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/SecurityRealm.java) | Core contract and default filter chain implementation |
| [`core/src/main/java/hudson/security/LegacySecurityRealm.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/LegacySecurityRealm.java) | Backward‑compatible realm delegating to servlet container authentication |
| [`core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java) | Default mutable user store with internal account management |
| [`core/src/main/java/hudson/security/AbstractPasswordBasedSecurityRealm.java`](https://github.com/jenkinsci/jenkins/blob/main/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`](https://github.com/jenkinsci/jenkins/blob/main/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.