CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-spring-security-core

Core authentication and authorization framework for Spring applications with comprehensive user management and security context handling

Overview
Eval results
Files

jaas-authentication.mddocs/

JAAS Authentication Integration

Overview

Spring Security provides comprehensive support for Java Authentication and Authorization Service (JAAS) integration. This allows applications to leverage existing JAAS LoginModules while benefiting from Spring Security's architecture and features.

Key Information for Agents

Core Capabilities:

  • JAAS authentication via JaasAuthenticationProvider and DefaultJaasAuthenticationProvider
  • Delegates to JAAS LoginContext for authentication
  • Authority mapping via AuthorityGranter (maps JAAS principals to Spring Security authorities)
  • Callback handling via JaasAuthenticationCallbackHandler for flexible authentication
  • Exception mapping via LoginExceptionResolver (JAAS exceptions to Spring Security exceptions)
  • Event publishing for JAAS authentication success/failure

Key Interfaces and Classes:

  • AbstractJaasAuthenticationProvider - Abstract base with JAAS integration
  • JaasAuthenticationProvider - Concrete implementation with explicit configuration
  • DefaultJaasAuthenticationProvider - Implementation with callback handler support
  • JaasAuthenticationToken - Authentication token containing LoginContext
  • AuthorityGranter - Interface: grant(Principal) returns Set of authority strings
  • JaasAuthenticationCallbackHandler - Interface for handling JAAS callbacks
  • LoginExceptionResolver - Interface: resolveException(LoginException) returns AuthenticationException
  • InMemoryConfiguration - In-memory JAAS configuration (for testing)

Default Behaviors:

  • Supports UsernamePasswordAuthenticationToken (via supports() method)
  • Authority granters called for each principal in authenticated subject
  • Default exception resolver: DefaultLoginExceptionResolver (maps common exceptions)
  • Callback handlers: JaasNameCallbackHandler, JaasPasswordCallbackHandler (extract from Authentication)

Threading Model:

  • Synchronous provider executes in calling thread
  • Thread-safe: Providers are stateless

Lifecycle:

  • JAAS configuration set via setConfiguration() (required)
  • Authority granters set via setAuthorityGranters() (required)
  • Login context name set via setLoginContextName() (required)
  • Exception resolver set via setLoginExceptionResolver() (optional)

Exceptions:

  • LoginException - JAAS exception (mapped to Spring Security exception via resolver)
  • BadCredentialsException - Mapped from FailedLoginException
  • AccountExpiredException - Mapped from JAAS AccountExpiredException
  • LockedException - Mapped from AccountLockedException
  • CredentialsExpiredException - Mapped from CredentialExpiredException

Edge Cases:

  • Multiple principals: Authority granter called for each principal in subject
  • Custom callbacks: Implement JaasAuthenticationCallbackHandler for custom callback types
  • SecurityContext integration: Use SecurityContextLoginModule in JAAS configuration
  • Configuration source: Can use InMemoryConfiguration or external JAAS config file
  • Authority mapping: Combine authorities from multiple granters (union of all grants)

Core Components

JAAS Authentication Providers

AbstractJaasAuthenticationProvider

Abstract base class for JAAS-based authentication providers.

public abstract class AbstractJaasAuthenticationProvider
    implements AuthenticationProvider, ApplicationEventPublisherAware { .api }

Description: Base provider that delegates authentication to JAAS LoginContext.

Abstract Methods:

protected abstract Configuration getConfiguration() { .api }
  • Returns the JAAS Configuration to use
  • Implementations must provide JAAS configuration
protected abstract AuthorityGranter[] getAuthorityGranters() { .api }
  • Returns array of AuthorityGranters for mapping JAAS principals to Spring Security authorities
  • Called after successful JAAS authentication

Methods:

public Authentication authenticate(Authentication auth)
    throws AuthenticationException { .api }
  • Authenticates using JAAS LoginContext
  • Returns JaasAuthenticationToken on success
public boolean supports(Class<?> aClass) { .api }
  • Supports UsernamePasswordAuthenticationToken
public void setLoginContextName(String loginContextName) { .api }
  • Sets the JAAS LoginContext name
  • Parameters: loginContextName - The name in JAAS configuration
public void setLoginExceptionResolver(
    LoginExceptionResolver loginExceptionResolver) { .api }
  • Sets resolver for mapping JAAS LoginExceptions to Spring Security exceptions
  • Parameters: loginExceptionResolver - Custom exception resolver
public void setApplicationEventPublisher(
    ApplicationEventPublisher applicationEventPublisher) { .api }
  • Sets event publisher for JAAS authentication events

Package: org.springframework.security.authentication.jaas

JaasAuthenticationProvider

Concrete implementation using explicit Configuration and AuthorityGranters.

public class JaasAuthenticationProvider
    extends AbstractJaasAuthenticationProvider { .api }

Description: JAAS provider with explicit configuration and authority mapping.

Constructor:

public JaasAuthenticationProvider() { .api }

Methods:

public void setConfiguration(Configuration configuration) { .api }
  • Sets the JAAS Configuration
  • Parameters: configuration - JAAS Configuration instance
public void setAuthorityGranters(AuthorityGranter[] authorityGranters) { .api }
  • Sets the authority granters
  • Parameters: authorityGranters - Array of AuthorityGranter implementations

Example:

@Bean
public JaasAuthenticationProvider jaasAuthenticationProvider() {
    JaasAuthenticationProvider provider = new JaasAuthenticationProvider();
    provider.setConfiguration(jaasConfiguration());
    provider.setAuthorityGranters(new AuthorityGranter[] {
        new SampleAuthorityGranter()
    });
    provider.setLoginContextName("Sample");
    return provider;
}

@Bean
public Configuration jaasConfiguration() {
    InMemoryConfiguration config = new InMemoryConfiguration();
    Map<String, AppConfigurationEntry[]> mappings = new HashMap<>();

    AppConfigurationEntry entry = new AppConfigurationEntry(
        SampleLoginModule.class.getName(),
        AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
        new HashMap<>()
    );
    mappings.put("Sample", new AppConfigurationEntry[] { entry });

    config.setMappings(mappings);
    return config;
}

DefaultJaasAuthenticationProvider

Provider implementation using callback handlers for flexible authentication.

public class DefaultJaasAuthenticationProvider
    extends AbstractJaasAuthenticationProvider { .api }

Description: JAAS provider supporting custom callback handlers.

Methods:

public void setCallbackHandlers(
    JaasAuthenticationCallbackHandler[] callbackHandlers) { .api }
  • Sets custom callback handlers for JAAS authentication
  • Parameters: callbackHandlers - Array of callback handler implementations

Example:

@Bean
public DefaultJaasAuthenticationProvider defaultJaasProvider() {
    DefaultJaasAuthenticationProvider provider =
        new DefaultJaasAuthenticationProvider();
    provider.setConfiguration(jaasConfiguration());
    provider.setLoginContextName("DefaultLogin");
    provider.setCallbackHandlers(new JaasAuthenticationCallbackHandler[] {
        new JaasNameCallbackHandler(),
        new JaasPasswordCallbackHandler()
    });
    provider.setAuthorityGranters(new AuthorityGranter[] {
        new TestAuthorityGranter()
    });
    return provider;
}

Authentication Token

JaasAuthenticationToken

Authentication token representing successful JAAS authentication.

public class JaasAuthenticationToken
    extends UsernamePasswordAuthenticationToken { .api }

Description: Token containing JAAS LoginContext and authenticated principals.

Constructor:

public JaasAuthenticationToken(
    Object principal,
    Object credentials,
    Collection<? extends GrantedAuthority> authorities,
    LoginContext loginContext) { .api }

Parameters:

  • principal - The authenticated principal
  • credentials - The credentials
  • authorities - The granted authorities
  • loginContext - The JAAS LoginContext

Methods:

public LoginContext getLoginContext() { .api }
  • Returns the JAAS LoginContext
  • Provides access to authenticated JAAS subjects

Example:

public void processAuthentication(Authentication auth) {
    if (auth instanceof JaasAuthenticationToken) {
        JaasAuthenticationToken jaasToken = (JaasAuthenticationToken) auth;
        LoginContext loginContext = jaasToken.getLoginContext();

        // Access JAAS Subject
        Subject subject = loginContext.getSubject();
        Set<Principal> principals = subject.getPrincipals();

        // Process JAAS principals
        for (Principal principal : principals) {
            System.out.println("JAAS Principal: " + principal.getName());
        }
    }
}

Authority Mapping

AuthorityGranter

Interface for mapping JAAS principals to Spring Security authorities.

public interface AuthorityGranter { .api }

Description: Strategy for granting authorities based on JAAS principals.

Methods:

Set<String> grant(Principal principal) { .api }
  • Grants authorities for given JAAS principal
  • Parameters: principal - JAAS Principal from authenticated subject
  • Returns: Set of authority strings (role names)

Example:

public class CustomAuthorityGranter implements AuthorityGranter {

    @Override
    public Set<String> grant(Principal principal) {
        Set<String> authorities = new HashSet<>();

        // Map specific principal types to roles
        if (principal instanceof AdminPrincipal) {
            authorities.add("ROLE_ADMIN");
            authorities.add("ROLE_USER");
        } else if (principal instanceof UserPrincipal) {
            authorities.add("ROLE_USER");
        }

        // Map based on principal name
        String name = principal.getName();
        if (name.startsWith("admin_")) {
            authorities.add("ROLE_ADMIN");
        }

        return authorities;
    }
}

JaasGrantedAuthority

GrantedAuthority implementation that wraps a JAAS Principal.

public class JaasGrantedAuthority implements GrantedAuthority { .api }

Description: Authority representing a JAAS Principal.

Constructor:

public JaasGrantedAuthority(String role, Principal principal) { .api }

Parameters:

  • role - The authority/role name
  • principal - The underlying JAAS Principal

Methods:

public String getAuthority() { .api }
  • Returns the role name
public Principal getPrincipal() { .api }
  • Returns the underlying JAAS Principal

Example:

public List<GrantedAuthority> mapPrincipals(Set<Principal> principals) {
    List<GrantedAuthority> authorities = new ArrayList<>();
    for (Principal principal : principals) {
        authorities.add(
            new JaasGrantedAuthority("ROLE_" + principal.getName(), principal)
        );
    }
    return authorities;
}

Callback Handlers

JaasAuthenticationCallbackHandler

Interface for handling JAAS Callbacks during authentication.

public interface JaasAuthenticationCallbackHandler { .api }

Description: Handles specific JAAS Callback types.

Methods:

void handle(Callback callback, Authentication authentication)
    throws IOException, UnsupportedCallbackException { .api }
  • Handles a JAAS callback
  • Parameters:
    • callback - The JAAS Callback to handle
    • authentication - The Spring Security Authentication containing credentials

JaasNameCallbackHandler

Handles NameCallback by extracting principal from Authentication.

public class JaasNameCallbackHandler
    implements JaasAuthenticationCallbackHandler { .api }

Description: Populates NameCallback with username from authentication.

Example:

public class CustomCallbackHandler
        implements JaasAuthenticationCallbackHandler {

    @Override
    public void handle(Callback callback, Authentication authentication)
            throws IOException, UnsupportedCallbackException {
        if (callback instanceof NameCallback) {
            NameCallback nameCallback = (NameCallback) callback;
            nameCallback.setName(authentication.getName());
        } else {
            throw new UnsupportedCallbackException(callback);
        }
    }
}

JaasPasswordCallbackHandler

Handles PasswordCallback by extracting credentials from Authentication.

public class JaasPasswordCallbackHandler
    implements JaasAuthenticationCallbackHandler { .api }

Description: Populates PasswordCallback with password from authentication.

Login Modules

SecurityContextLoginModule

JAAS LoginModule that populates SecurityContext with authenticated subject.

public class SecurityContextLoginModule implements LoginModule { .api }

Description: LoginModule that integrates JAAS authentication with Spring Security's SecurityContext.

Methods:

public void initialize(Subject subject, CallbackHandler callbackHandler,
    Map<String, ?> sharedState, Map<String, ?> options) { .api }
  • Initializes the login module
public boolean login() throws LoginException { .api }
  • Performs authentication (always returns true - relies on other modules)
public boolean commit() throws LoginException { .api }
  • Commits authentication and sets SecurityContext
public boolean abort() throws LoginException { .api }
  • Aborts authentication
public boolean logout() throws LoginException { .api }
  • Logs out and clears SecurityContext

Configuration:

<!-- JAAS configuration file -->
<Sample {
    com.example.CustomLoginModule required;
    org.springframework.security.authentication.jaas.SecurityContextLoginModule required;
};>

Example:

// Use in JAAS configuration
public Configuration createConfiguration() {
    AppConfigurationEntry securityContextEntry =
        new AppConfigurationEntry(
            SecurityContextLoginModule.class.getName(),
            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
            Collections.emptyMap()
        );

    AppConfigurationEntry customEntry =
        new AppConfigurationEntry(
            CustomLoginModule.class.getName(),
            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
            Collections.emptyMap()
        );

    InMemoryConfiguration config = new InMemoryConfiguration();
    config.setMappings(Map.of("MyApp",
        new AppConfigurationEntry[] { customEntry, securityContextEntry }
    ));
    return config;
}

Exception Handling

LoginExceptionResolver

Interface for resolving JAAS LoginExceptions to Spring Security exceptions.

public interface LoginExceptionResolver { .api }

Description: Strategy for mapping JAAS exceptions to Spring Security exceptions.

Methods:

AuthenticationException resolveException(LoginException exception) { .api }
  • Resolves LoginException to AuthenticationException
  • Parameters: exception - JAAS LoginException
  • Returns: Appropriate Spring Security AuthenticationException

DefaultLoginExceptionResolver

Default implementation mapping common JAAS exceptions.

public class DefaultLoginExceptionResolver
    implements LoginExceptionResolver { .api }

Description: Maps standard JAAS exceptions to Spring Security exceptions.

Mappings:

  • FailedLoginExceptionBadCredentialsException
  • AccountExpiredExceptionAccountExpiredException
  • CredentialExpiredExceptionCredentialsExpiredException
  • AccountLockedExceptionLockedException

Example:

public class CustomLoginExceptionResolver
        implements LoginExceptionResolver {

    @Override
    public AuthenticationException resolveException(
            LoginException exception) {
        if (exception instanceof FailedLoginException) {
            return new BadCredentialsException(
                "Invalid credentials", exception);
        } else if (exception instanceof AccountExpiredException) {
            return new org.springframework.security.authentication
                .AccountExpiredException(
                    "Account expired", exception);
        }
        // Default fallback
        return new AuthenticationServiceException(
            "Login failed", exception);
    }
}

In-Memory Configuration

InMemoryConfiguration

JAAS Configuration implementation storing configuration in memory.

public class InMemoryConfiguration extends Configuration { .api }

Description: In-memory JAAS configuration for testing and simple scenarios.

Methods:

public AppConfigurationEntry[] getAppConfigurationEntry(String name) { .api }
  • Returns configuration entries for given application name
public void setMappings(
    Map<String, AppConfigurationEntry[]> mappings) { .api }
  • Sets the configuration mappings
  • Parameters: mappings - Map of application name to configuration entries

Package: org.springframework.security.authentication.jaas.memory

Example:

@Bean
public Configuration jaasConfiguration() {
    InMemoryConfiguration config = new InMemoryConfiguration();

    Map<String, Object> options = new HashMap<>();
    options.put("debug", "true");

    AppConfigurationEntry entry = new AppConfigurationEntry(
        "com.example.MyLoginModule",
        AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
        options
    );

    Map<String, AppConfigurationEntry[]> mappings = new HashMap<>();
    mappings.put("MyApplication", new AppConfigurationEntry[] { entry });

    config.setMappings(mappings);
    return config;
}

JAAS Events

JaasAuthenticationEvent

Base class for JAAS authentication events.

public abstract class JaasAuthenticationEvent extends ApplicationEvent { .api }

Methods:

public JaasAuthenticationToken getAuthenticationToken() { .api }
  • Returns the JAAS authentication token

Package: org.springframework.security.authentication.jaas.event

JaasAuthenticationSuccessEvent

Published when JAAS authentication succeeds.

public class JaasAuthenticationSuccessEvent extends JaasAuthenticationEvent { .api }

Constructor:

public JaasAuthenticationSuccessEvent(JaasAuthenticationToken token) { .api }

JaasAuthenticationFailedEvent

Published when JAAS authentication fails.

public class JaasAuthenticationFailedEvent extends JaasAuthenticationEvent { .api }

Constructor:

public JaasAuthenticationFailedEvent(
    JaasAuthenticationToken token,
    AuthenticationException exception) { .api }

Methods:

public AuthenticationException getException() { .api }
  • Returns the exception that caused failure

Example:

@Component
public class JaasEventListener {

    @EventListener
    public void onJaasSuccess(JaasAuthenticationSuccessEvent event) {
        JaasAuthenticationToken token = event.getAuthenticationToken();
        LoginContext loginContext = token.getLoginContext();
        Subject subject = loginContext.getSubject();

        System.out.println("JAAS authentication successful");
        System.out.println("Subject principals: " +
            subject.getPrincipals().size());
    }

    @EventListener
    public void onJaasFailure(JaasAuthenticationFailedEvent event) {
        AuthenticationException exception = event.getException();
        System.err.println("JAAS authentication failed: " +
            exception.getMessage());
    }
}

Complete Configuration Example

@Configuration
public class JaasSecurityConfig {

    @Bean
    public JaasAuthenticationProvider jaasAuthenticationProvider() {
        JaasAuthenticationProvider provider = new JaasAuthenticationProvider();
        provider.setConfiguration(jaasConfiguration());
        provider.setLoginContextName("MyApplication");
        provider.setAuthorityGranters(authorityGranters());
        provider.setLoginExceptionResolver(new DefaultLoginExceptionResolver());
        return provider;
    }

    @Bean
    public Configuration jaasConfiguration() {
        InMemoryConfiguration config = new InMemoryConfiguration();

        Map<String, Object> options = Map.of(
            "debug", "false",
            "useTicketCache", "true"
        );

        AppConfigurationEntry loginModule = new AppConfigurationEntry(
            CustomLoginModule.class.getName(),
            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
            options
        );

        AppConfigurationEntry securityContextModule =
            new AppConfigurationEntry(
                SecurityContextLoginModule.class.getName(),
                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                Collections.emptyMap()
            );

        config.setMappings(Map.of("MyApplication",
            new AppConfigurationEntry[] { loginModule, securityContextModule }
        ));

        return config;
    }

    @Bean
    public AuthorityGranter[] authorityGranters() {
        return new AuthorityGranter[] {
            new AdminAuthorityGranter(),
            new UserAuthorityGranter()
        };
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(
            Collections.singletonList(jaasAuthenticationProvider())
        );
    }
}

// Custom authority granter
public class AdminAuthorityGranter implements AuthorityGranter {
    @Override
    public Set<String> grant(Principal principal) {
        if (principal.getName().contains("admin")) {
            return Set.of("ROLE_ADMIN", "ROLE_USER");
        }
        return Collections.emptySet();
    }
}

// Custom login module
public class CustomLoginModule implements LoginModule {
    private Subject subject;
    private CallbackHandler callbackHandler;
    private boolean succeeded = false;
    private Principal userPrincipal;

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler,
                          Map<String, ?> sharedState, Map<String, ?> options) {
        this.subject = subject;
        this.callbackHandler = callbackHandler;
    }

    @Override
    public boolean login() throws LoginException {
        NameCallback nameCallback = new NameCallback("Username: ");
        PasswordCallback passwordCallback =
            new PasswordCallback("Password: ", false);

        try {
            callbackHandler.handle(
                new Callback[] { nameCallback, passwordCallback }
            );

            String username = nameCallback.getName();
            char[] password = passwordCallback.getPassword();

            // Perform authentication
            if (authenticate(username, password)) {
                userPrincipal = new UserPrincipal(username);
                succeeded = true;
                return true;
            }
            throw new FailedLoginException("Authentication failed");
        } catch (IOException | UnsupportedCallbackException e) {
            throw new LoginException(e.getMessage());
        }
    }

    @Override
    public boolean commit() throws LoginException {
        if (succeeded) {
            subject.getPrincipals().add(userPrincipal);
            return true;
        }
        return false;
    }

    @Override
    public boolean abort() throws LoginException {
        succeeded = false;
        userPrincipal = null;
        return true;
    }

    @Override
    public boolean logout() throws LoginException {
        subject.getPrincipals().remove(userPrincipal);
        succeeded = false;
        userPrincipal = null;
        return true;
    }

    private boolean authenticate(String username, char[] password) {
        // Implement authentication logic
        return true;
    }
}

Best Practices

  1. Use SecurityContextLoginModule - Include it in your JAAS configuration to integrate with Spring Security
  2. Implement custom AuthorityGranters - Map JAAS principals to appropriate Spring Security roles
  3. Handle exceptions properly - Use LoginExceptionResolver for consistent exception handling
  4. Configure callback handlers - Provide handlers for all callback types your LoginModules require
  5. Test with InMemoryConfiguration - Use for unit tests and development
  6. Publish events - Configure event publishing for audit logging
  7. Secure LoginModule classes - Ensure LoginModule implementations are secure

See Also

  • Authentication Architecture
  • Authentication Events
  • Java JAAS documentation

Install with Tessl CLI

npx tessl i tessl/maven-spring-security-core

docs

aot-native-support.md

authentication-core.md

authentication-events.md

authentication-management.md

authentication-tokens.md

authorities.md

authorization.md

compromised-password.md

concurrent-async.md

dao-authentication.md

expression-access-control.md

index.md

jaas-authentication.md

jackson-serialization.md

method-security.md

observation-metrics.md

one-time-tokens.md

provisioning.md

security-context.md

session-management.md

user-details.md

tile.json