or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

aot-native-support.mdauthentication-core.mdauthentication-events.mdauthentication-management.mdauthentication-tokens.mdauthorities.mdauthorization.mdcompromised-password.mdconcurrent-async.mddao-authentication.mdexpression-access-control.mdindex.mdjaas-authentication.mdjackson-serialization.mdmethod-security.mdobservation-metrics.mdone-time-tokens.mdprovisioning.mdsecurity-context.mdsession-management.mduser-details.md
tile.json

method-security.mddocs/

Method Security

Method security provides fine-grained authorization control at the method level using annotations and AOP interceptors. This comprehensive framework supports pre/post authorization, filtering, and custom authorization handlers.

Key Information for Agents

Core Capabilities:

  • Method-level security via annotations: @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter, @Secured, @AuthorizeReturnObject
  • SpEL expression evaluation for dynamic authorization decisions
  • AOP-based interception via MethodInterceptor implementations
  • Support for custom denial handlers via @HandleAuthorizationDenied
  • Reactive support via reactive method interceptors

Key Interfaces and Classes:

  • AuthorizationManagerBeforeMethodInterceptor - Pre-authorization interceptor (factory methods: preAuthorize(), secured(), jsr250())
  • AuthorizationManagerAfterMethodInterceptor - Post-authorization interceptor (factory method: postAuthorize())
  • PreFilterAuthorizationMethodInterceptor - Filters method parameters before invocation
  • PostFilterAuthorizationMethodInterceptor - Filters return values after invocation
  • AuthorizeReturnObjectMethodInterceptor - Applies authorization to returned objects
  • PreAuthorizeAuthorizationManager - Evaluates @PreAuthorize SpEL expressions
  • PostAuthorizeAuthorizationManager - Evaluates @PostAuthorize SpEL expressions
  • SecuredAuthorizationManager - Handles @Secured annotations
  • Jsr250AuthorizationManager - Handles JSR-250 annotations (requires jakarta.annotation-api dependency)
  • MethodAuthorizationDeniedHandler - Interface for custom denial handling

Default Behaviors:

  • @PreAuthorize - Expression must evaluate to true for method to execute
  • @PostAuthorize - Expression evaluated after method execution with access to returnObject
  • @PreFilter - Filters collection parameters before method execution (uses filterObject variable)
  • @PostFilter - Filters returned collections after method execution
  • @Secured - Requires any one of the specified roles/authorities
  • @AuthorizeReturnObject - Creates proxy on return value enforcing method-level security
  • Default denial handler: ThrowingMethodAuthorizationDeniedHandler (throws AuthorizationDeniedException)
  • Interceptor order defined by AuthorizationInterceptorsOrder enum

Threading Model:

  • Synchronous interceptors execute in calling thread
  • Reactive interceptors return Mono / Flux for non-blocking execution
  • Security context propagated automatically via AOP

Lifecycle:

  • Interceptors are Spring AOP advisors (implement PointcutAdvisor)
  • Configured as @Bean methods returning Advisor
  • Expression handlers are beans with configurable components (permission evaluator, role hierarchy, etc.)

Exceptions:

  • AuthorizationDeniedException - Thrown when authorization denied (default behavior)
  • NullReturningMethodAuthorizationDeniedHandler - Returns null instead of throwing (since 6.5)
  • Custom handlers can return any value or throw custom exceptions

Edge Cases:

  • Method parameters: Accessible in SpEL via #paramName (requires parameter name discovery)
  • Return values: Accessible in @PostAuthorize via returnObject variable
  • Filtering: @PreFilter / @PostFilter work on Collections and Arrays
  • Multiple collection parameters: Use filterTarget attribute in @PreFilter to specify which parameter
  • Null return values: @PostAuthorize expressions must handle null returnObject
  • Proxy creation: @AuthorizeReturnObject requires AuthorizationProxyFactory bean
  • JSR-250 support: Requires jakarta.annotation-api dependency for @RolesAllowed, @PermitAll, @DenyAll
  • Expression evaluation: Uses MethodSecurityExpressionHandler (default: DefaultMethodSecurityExpressionHandler)

Core Annotations

@PreAuthorize

Evaluates a SpEL expression before method execution to determine if the invocation should proceed.

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(String username) {
    // Method execution
}

Annotation Definition:

@PreAuthorize(String value)

{ .api }

  • value: SpEL expression that must evaluate to true for authorization to be granted
  • Target: Method or Type
  • Inherited: Yes

@PostAuthorize

Evaluates a SpEL expression after method execution, with access to the return value via returnObject.

@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long id) {
    return documentRepository.findById(id);
}

Annotation Definition:

@PostAuthorize(String value)

{ .api }

  • value: SpEL expression evaluated after method execution
  • Access to: returnObject, authentication, method parameters

@PreFilter

Filters a collection parameter before method execution based on a SpEL expression.

@PreFilter(value = "filterObject.owner == authentication.name",
           filterTarget = "documents")
public void processDocuments(List<Document> documents) {
    // Only documents owned by current user are processed
}

Annotation Definition:

@PreFilter(String value, String filterTarget = "")

{ .api }

  • value: SpEL expression evaluated for each collection element
  • filterTarget: Parameter name to filter (required if multiple collection parameters)
  • filterObject: Variable representing each collection element

@PostFilter

Filters the returned collection after method execution.

@PostFilter("filterObject.isPublic or filterObject.owner == authentication.name")
public List<Document> getAllDocuments() {
    return documentRepository.findAll();
}

Annotation Definition:

@PostFilter(String value)

{ .api }

  • value: SpEL expression evaluated for each returned collection element
  • filterObject: Variable representing each returned element

@Secured

Legacy annotation specifying required security attributes (roles or authorities).

@Secured({"ROLE_ADMIN", "ROLE_MODERATOR"})
public void moderateContent() {
    // Method execution
}

Annotation Definition:

@Secured(String[] value)

{ .api }

  • value: Array of required security attributes (any one required)

@AuthorizeReturnObject

Applies authorization to the returned object, creating a proxy that enforces method-level security on the return value.

@AuthorizeReturnObject
public UserService getUserService() {
    return new UserServiceImpl();
}

Annotation Definition:

@AuthorizeReturnObject

{ .api }

  • Target: Method or Type

@HandleAuthorizationDenied

Specifies a custom handler when authorization is denied, instead of throwing an exception.

@PreAuthorize("hasRole('ADMIN')")
@HandleAuthorizationDenied(handlerClass = MyDeniedHandler.class)
public Document getDocument(Long id) {
    return documentRepository.findById(id);
}

Annotation Definition:

@HandleAuthorizationDenied(
    Class<? extends MethodAuthorizationDeniedHandler> handlerClass = void.class,
    String handlerMethod = ""
)

{ .api }

  • handlerClass: Handler class implementing MethodAuthorizationDeniedHandler
  • handlerMethod: Method name to invoke on handler

Method Interceptors

AuthorizationManagerBeforeMethodInterceptor

Pre-authorization interceptor that evaluates authorization before method invocation.

public class AuthorizationManagerBeforeMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

Static Factory Methods:

static AuthorizationManagerBeforeMethodInterceptor preAuthorize()

{ .api }

Creates interceptor for @PreAuthorize annotations.

static AuthorizationManagerBeforeMethodInterceptor preAuthorize(
    AuthorizationManager<MethodInvocation> authorizationManager
)

{ .api }

Creates interceptor with custom authorization manager.

static AuthorizationManagerBeforeMethodInterceptor secured()

{ .api }

Creates interceptor for @Secured annotations.

static AuthorizationManagerBeforeMethodInterceptor jsr250()

{ .api }

Creates interceptor for JSR-250 annotations (@RolesAllowed, @PermitAll, @DenyAll).

Example Configuration:

@Bean
public Advisor preAuthorizeAdvisor() {
    return AuthorizationManagerBeforeMethodInterceptor.preAuthorize();
}

AuthorizationManagerAfterMethodInterceptor

Post-authorization interceptor that evaluates authorization after method completion.

public class AuthorizationManagerAfterMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

Static Factory Methods:

static AuthorizationManagerAfterMethodInterceptor postAuthorize()

{ .api }

Creates interceptor for @PostAuthorize annotations.

static AuthorizationManagerAfterMethodInterceptor postAuthorize(
    AuthorizationManager<MethodInvocationResult> authorizationManager
)

{ .api }

Creates interceptor with custom authorization manager.

PreFilterAuthorizationMethodInterceptor

Filters method parameters before invocation based on @PreFilter annotations.

public class PreFilterAuthorizationMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

Usage:

@Bean
public Advisor preFilterAdvisor() {
    return new PreFilterAuthorizationMethodInterceptor();
}

PostFilterAuthorizationMethodInterceptor

Filters method return values after invocation based on @PostFilter annotations.

public class PostFilterAuthorizationMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

Usage:

@Bean
public Advisor postFilterAdvisor() {
    return new PostFilterAuthorizationMethodInterceptor();
}

AuthorizeReturnObjectMethodInterceptor

Applies authorization to returned objects based on @AuthorizeReturnObject annotation.

public class AuthorizeReturnObjectMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

Usage:

@Bean
public Advisor authorizeReturnObjectAdvisor(
    AuthorizationProxyFactory proxyFactory
) {
    return new AuthorizeReturnObjectMethodInterceptor(proxyFactory);
}

Reactive Method Interceptors

AuthorizationManagerBeforeReactiveMethodInterceptor

Reactive pre-authorization interceptor for non-blocking operations.

public class AuthorizationManagerBeforeReactiveMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

Static Factory Methods:

static AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorize()

{ .api }

static AuthorizationManagerBeforeReactiveMethodInterceptor secured()

{ .api }

static AuthorizationManagerBeforeReactiveMethodInterceptor jsr250()

{ .api }

AuthorizationManagerAfterReactiveMethodInterceptor

Reactive post-authorization interceptor.

public class AuthorizationManagerAfterReactiveMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

PreFilterAuthorizationReactiveMethodInterceptor

Reactive pre-filter interceptor.

public class PreFilterAuthorizationReactiveMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

PostFilterAuthorizationReactiveMethodInterceptor

Reactive post-filter interceptor.

public class PostFilterAuthorizationReactiveMethodInterceptor
    implements MethodInterceptor, PointcutAdvisor

{ .api }

Authorization Managers

PreAuthorizeAuthorizationManager

Authorization manager for @PreAuthorize annotations, evaluating SpEL expressions.

public class PreAuthorizeAuthorizationManager
    implements AuthorizationManager<MethodInvocation>

{ .api }

Key Methods:

void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler)

{ .api }

Sets custom expression handler for SpEL evaluation.

PostAuthorizeAuthorizationManager

Authorization manager for @PostAuthorize annotations.

public class PostAuthorizeAuthorizationManager
    implements AuthorizationManager<MethodInvocationResult>

{ .api }

Key Methods:

void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler)

{ .api }

SecuredAuthorizationManager

Authorization manager for @Secured annotations.

public class SecuredAuthorizationManager
    implements AuthorizationManager<MethodInvocation>

{ .api }

Example:

@Bean
public SecuredAuthorizationManager securedAuthorizationManager() {
    return new SecuredAuthorizationManager();
}

Jsr250AuthorizationManager

Authorization manager for JSR-250 annotations (@RolesAllowed, @PermitAll, @DenyAll).

public class Jsr250AuthorizationManager
    implements AuthorizationManager<MethodInvocation>

{ .api }

Example:

@Bean
public Jsr250AuthorizationManager jsr250AuthorizationManager() {
    return new Jsr250AuthorizationManager();
}

MethodExpressionAuthorizationManager

Generic authorization manager using SpEL expressions for method security.

public class MethodExpressionAuthorizationManager
    implements AuthorizationManager<MethodInvocation>

{ .api }

Usage:

MethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
MethodExpressionAuthorizationManager manager =
    new MethodExpressionAuthorizationManager(handler, "hasRole('ADMIN')");

Reactive Authorization Managers

PreAuthorizeReactiveAuthorizationManager:

public class PreAuthorizeReactiveAuthorizationManager
    implements ReactiveAuthorizationManager<MethodInvocation>

{ .api }

PostAuthorizeReactiveAuthorizationManager:

public class PostAuthorizeReactiveAuthorizationManager
    implements ReactiveAuthorizationManager<MethodInvocationResult>

{ .api }

Authorization Denial Handlers

MethodAuthorizationDeniedHandler

Interface for handling authorization denials at method level.

public interface MethodAuthorizationDeniedHandler

{ .api }

Key Methods:

Object handleDeniedInvocation(
    MethodInvocation methodInvocation,
    AuthorizationResult authorizationResult
)

{ .api }

Handles denied invocation before method execution.

Object handleDeniedInvocationResult(
    MethodInvocationResult methodInvocationResult,
    AuthorizationResult authorizationResult
)

{ .api }

Handles denied invocation after method execution.

NullReturningMethodAuthorizationDeniedHandler

Returns null when authorization is denied instead of throwing exception.

public class NullReturningMethodAuthorizationDeniedHandler
    implements MethodAuthorizationDeniedHandler

{ .api }

Example:

@PreAuthorize("hasRole('ADMIN')")
@HandleAuthorizationDenied(handlerClass = NullReturningMethodAuthorizationDeniedHandler.class)
public Document getDocument(Long id) {
    return documentRepository.findById(id);
}
// Returns null instead of throwing AccessDeniedException

ReflectiveMethodAuthorizationDeniedHandler

Invokes a specified method when authorization is denied, allowing custom fallback logic.

public class ReflectiveMethodAuthorizationDeniedHandler
    implements MethodAuthorizationDeniedHandler

{ .api }

Example:

public class DocumentService {

    @PreAuthorize("hasRole('ADMIN')")
    @HandleAuthorizationDenied(handlerClass = ReflectiveMethodAuthorizationDeniedHandler.class,
                                handlerMethod = "handleDenied")
    public Document getDocument(Long id) {
        return documentRepository.findById(id);
    }

    private Document handleDenied(MethodInvocation invocation,
                                   AuthorizationResult result) {
        return Document.publicPlaceholder();
    }
}

Method Invocation Support

MethodInvocationResult

Represents the result of a method invocation for post-authorization checks.

public class MethodInvocationResult

{ .api }

Key Methods:

MethodInvocation getMethodInvocation()

{ .api }

Returns the original method invocation.

Object getResult()

{ .api }

Returns the result of the method execution.

Example:

MethodInvocationResult result = new MethodInvocationResult(invocation, returnValue);
AuthorizationResult decision = postAuthManager.authorize(auth, result);

Authorization Proxy Support

AuthorizationProxy

Marker interface indicating an object is an authorization proxy.

public interface AuthorizationProxy

{ .api }

Key Methods:

Object __AUTHORIZE__()

{ .api }

Triggers authorization checks on the proxied object.

AuthorizationAdvisorProxyFactory

Creates authorization proxies using Spring AOP advisors.

public class AuthorizationAdvisorProxyFactory
    implements AuthorizationProxyFactory

{ .api }

Usage:

AuthorizationAdvisorProxyFactory factory = new AuthorizationAdvisorProxyFactory();
factory.setAdvisors(preAuthorizeAdvisor, postAuthorizeAdvisor);

UserService proxiedService = (UserService) factory.proxy(
    userService,
    UserService.class
);

Method Security Configuration

AuthorizationInterceptorsOrder

Defines the order of authorization interceptors.

public class AuthorizationInterceptorsOrder

{ .api }

Constants:

int PRE_AUTHORIZE
int PRE_FILTER
int POST_AUTHORIZE
int POST_FILTER
int SECURED
int JSR250

{ .api }

Usage:

@Bean
@Order(AuthorizationInterceptorsOrder.PRE_AUTHORIZE)
public Advisor preAuthorizeAdvisor() {
    return AuthorizationManagerBeforeMethodInterceptor.preAuthorize();
}

AuthorizationMethodPointcuts

Utility for creating pointcuts for method security annotations.

public class AuthorizationMethodPointcuts

{ .api }

Static Methods:

static Pointcut forAnnotations(Class<? extends Annotation>... annotations)

{ .api }

Creates a pointcut matching methods with specified annotations.

Example:

Pointcut pointcut = AuthorizationMethodPointcuts.forAnnotations(
    PreAuthorize.class,
    PostAuthorize.class
);

NoOpAuthorizationEventPublisher

No-operation authorization event publisher for method security.

public class NoOpAuthorizationEventPublisher
    implements AuthorizationEventPublisher

{ .api }

Usage:

@Bean
public AuthorizationEventPublisher noOpEventPublisher() {
    return new NoOpAuthorizationEventPublisher();
}

Expression Handling

MethodSecurityExpressionHandler

Interface for creating and evaluating security expressions in method security context.

public interface MethodSecurityExpressionHandler
    extends SecurityExpressionHandler<MethodInvocation>

{ .api }

Key Methods:

Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx)

{ .api }

Filters a collection based on the expression.

void setReturnObject(Object returnObject, EvaluationContext ctx)

{ .api }

Sets the return object in the evaluation context for post-authorization.

DefaultMethodSecurityExpressionHandler

Default implementation of method security expression handling.

public class DefaultMethodSecurityExpressionHandler
    extends AbstractSecurityExpressionHandler
    implements MethodSecurityExpressionHandler

{ .api }

Key Methods:

void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer)

{ .api }

Sets the strategy for discovering parameter names.

void setTrustResolver(AuthenticationTrustResolver trustResolver)

{ .api }

Sets the trust resolver for evaluating authentication types.

Example Configuration:

@Bean
public DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler() {
    DefaultMethodSecurityExpressionHandler handler =
        new DefaultMethodSecurityExpressionHandler();
    handler.setPermissionEvaluator(new CustomPermissionEvaluator());
    handler.setRoleHierarchy(roleHierarchy());
    handler.setDefaultRolePrefix("ROLE_");
    return handler;
}

MethodSecurityExpressionOperations

Interface defining operations available in method security SpEL expressions.

public interface MethodSecurityExpressionOperations
    extends SecurityExpressionOperations

{ .api }

Available in Expressions:

  • authentication - Current Authentication object
  • principal - Principal from authentication
  • hasRole(String) - Check for role
  • hasAuthority(String) - Check for authority
  • hasPermission(Object, Object) - Permission check
  • filterObject - Current object in filter expression
  • returnObject - Method return value in post-authorization

MethodSecurityExpressionRoot

Root object for method security expression evaluation.

public class MethodSecurityExpressionRoot
    extends SecurityExpressionRoot
    implements MethodSecurityExpressionOperations

{ .api }

Expression Variables:

@PreAuthorize("hasRole('ADMIN') or #username == authentication.name")
public void updateUser(String username, User user) {
    // Method parameters accessible via #paramName
}

@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long id) {
    // returnObject available after execution
}

@PreFilter("filterObject.isActive()")
public void processUsers(List<User> users) {
    // filterObject represents each collection element
}

MethodSecurityEvaluationContext

Evaluation context for method security expressions with lazy variable resolution.

public class MethodSecurityEvaluationContext extends StandardEvaluationContext

{ .api }

Features:

  • Lazy parameter resolution
  • Method parameter name discovery
  • Custom variable support

Complete Configuration Example

@Configuration
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig {

    @Bean
    public DefaultMethodSecurityExpressionHandler expressionHandler() {
        DefaultMethodSecurityExpressionHandler handler =
            new DefaultMethodSecurityExpressionHandler();
        handler.setPermissionEvaluator(permissionEvaluator());
        handler.setRoleHierarchy(roleHierarchy());
        return handler;
    }

    @Bean
    public PermissionEvaluator permissionEvaluator() {
        return new CustomPermissionEvaluator();
    }

    @Bean
    public RoleHierarchy roleHierarchy() {
        return RoleHierarchyImpl.withDefaultRolePrefix()
            .role("ADMIN").implies("USER")
            .role("USER").implies("GUEST")
            .build();
    }
}

@Service
public class SecuredService {

    @PreAuthorize("hasRole('ADMIN')")
    public void adminOnly() {
        // Admin-only operation
    }

    @PreAuthorize("#username == authentication.name or hasRole('ADMIN')")
    public User getUser(String username) {
        return userRepository.findByUsername(username);
    }

    @PostAuthorize("returnObject.owner == authentication.name")
    public Document getDocument(Long id) {
        return documentRepository.findById(id);
    }

    @PreFilter("filterObject.isPublic or filterObject.owner == authentication.name")
    @PostFilter("hasPermission(filterObject, 'READ')")
    public List<Document> getDocuments(List<Long> ids) {
        return documentRepository.findAllById(ids);
    }

    @PreAuthorize("hasRole('USER')")
    @HandleAuthorizationDenied(handlerClass = NullReturningMethodAuthorizationDeniedHandler.class)
    public Document getOptionalDocument(Long id) {
        return documentRepository.findById(id);
    }
}

Package

org.springframework.security.authorization.method