giuseppe-trisciuoglio/developer-kit

unit-test-security-authorization

Provides patterns for unit testing Spring Security with @PreAuthorize, @Secured, @RolesAllowed.

Voir la source
Document Skill original

Rendu depuis le dépôt source en conservant titres, exemples, code, tableaux, liens et images.

Unit Testing Security and Authorization

Overview

This skill provides patterns for unit testing Spring Security authorization logic using @PreAuthorize, @Secured, @RolesAllowed, and custom permission evaluators. It covers testing role-based access control (RBAC), expression-based authorization, custom permission evaluators, and verifying access denied scenarios without full Spring Security context.

When to Use

Use this skill when:

  • Testing @PreAuthorize and @Secured method-level security
  • Testing role-based access control (RBAC)
  • Testing custom permission evaluators
  • Verifying access denied scenarios
  • Testing authorization with authenticated principals
  • Want fast authorization tests without full Spring Security context

Instructions

Follow these steps to test Spring Security authorization:

1. Set Up Security Testing Dependencies

Add spring-security-test to your test dependencies:

xml
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-test</artifactId>
  <scope>test</scope>
</dependency>

2. Enable Method Security in Test Configuration

java
@Configuration
@EnableMethodSecurity
class TestSecurityConfig { }

3. Test with @WithMockUser

java
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminAccess() {
  assertThatCode(() -> service.deleteUser(1L))
    .doesNotThrowAnyException();
}

@Test
@WithMockUser(roles = "USER")
void shouldDenyUserAccess() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}

4. Test Custom Permission Evaluators

java
@Test
void shouldGrantPermissionToOwner() {
  Authentication auth = new UsernamePasswordAuthenticationToken(
    "alice", null, List.of(new SimpleGrantedAuthority("ROLE_USER"))
  );
  Document doc = new Document(1L, "Test", new User("alice"));

  boolean result = evaluator.hasPermission(auth, doc, "WRITE");
  assertThat(result).isTrue();
}

5. Validate Security is Active

If tests pass unexpectedly, add this assertion to verify security is enforced:

java
@Test
void shouldRejectUnauthorizedWhenSecurityEnabled() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}

Quick Reference

AnnotationDescriptionExample
@PreAuthorizePre-invocation authorization@PreAuthorize("hasRole('ADMIN')")
@PostAuthorizePost-invocation authorization@PostAuthorize("returnObject.owner == authentication.name")
@SecuredSimple role-based security@Secured("ROLE_ADMIN")
@RolesAllowedJSR-250 standard@RolesAllowed({"ADMIN", "MANAGER"})
@WithMockUserTest annotation@WithMockUser(roles = "ADMIN")

Examples

Basic @PreAuthorize Test

java
@Service
public class UserService {
  @PreAuthorize("hasRole('ADMIN')")
  public void deleteUser(Long userId) {
    // delete logic
  }
}

// Test
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminToDeleteUser() {
  assertThatCode(() -> service.deleteUser(1L))
    .doesNotThrowAnyException();
}

@Test
@WithMockUser(roles = "USER")
void shouldDenyUserFromDeletingUser() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}

Expression-Based Security Test

java
@PreAuthorize("#userId == authentication.principal.id")
public UserProfile getUserProfile(Long userId) {
  // get profile
}

// For custom principal properties, use @WithUserDetails with a custom UserDetailsService
@Test
@WithUserDetails("alice")
void shouldAllowUserToAccessOwnProfile() {
  assertThatCode(() -> service.getUserProfile(1L))
    .doesNotThrowAnyException();
}
Validation tip: If a security test passes unexpectedly, verify that @EnableMethodSecurity is active on the test configuration — a missing annotation causes all @PreAuthorize checks to be bypassed silently.

See references/basic-testing.md for more basic patterns and references/advanced-authorization.md for complex expressions and custom evaluators.

Best Practices

  1. Use `@WithMockUser` for setting authenticated user context
  2. Test both allow and deny cases for each security rule
  3. Test with different roles to verify role-based decisions
  4. Test expression-based security comprehensively
  5. Mock external dependencies (permission evaluators, etc.)
  6. Test anonymous access separately from authenticated access
  7. Use `@EnableGlobalMethodSecurity` in configuration for method-level security

Common Pitfalls

  • Forgetting to enable method security in test configuration
  • Not testing both allow and deny scenarios
  • Testing framework code instead of authorization logic
  • Not handling null authentication in tests
  • Mixing authentication and authorization tests unnecessarily

Constraints and Warnings

  • Method security requires proxy: @PreAuthorize works via proxies; direct method calls bypass security
  • `@EnableGlobalMethodSecurity`: Must be enabled for @PreAuthorize, @Secured to work
  • Role prefix: Spring adds "ROLE" prefix automatically; use `hasRole('ADMIN')` not `hasRole('ROLEADMIN')`
  • Authentication context: Security context is thread-local; be careful with async tests
  • `@WithMockUser` limitations: Creates a simple Authentication; complex auth scenarios need custom setup
  • SpEL expressions: Complex SpEL in @PreAuthorize can be difficult to debug; test thoroughly
  • Performance impact: Method security adds overhead; consider security at layer boundaries

References

Setup and Configuration

  • [references/setup.md](references/setup.md) - Maven/Gradle dependencies and security configuration

Testing Patterns

  • [references/basic-testing.md](references/basic-testing.md) - Basic patterns for @PreAuthorize, @Secured, MockMvc testing, and parameterized tests

Advanced Topics

  • [references/advanced-authorization.md](references/advanced-authorization.md) - Expression-based authorization, custom permission evaluators, SpEL expressions

Complete Examples

  • [references/complete-examples.md](references/complete-examples.md) - Before/after examples showing transition from manual to declarative security
du même dépôt

Autres Skills

Tous les Skills
giuseppe-trisciuoglio
Communauté

tailwind-css-patterns

Provides comprehensive Tailwind CSS utility-first styling patterns including responsive design, layout utilities, flexbox, grid, spacing, typography, colors, and modern CSS best practices. Use when styling React/Vue/Svelte components, building responsive layouts, implementing design systems, or optimizing CSS workflow.

installations
6
GitHub Stars
337
Mis à jour
18 août
giuseppe-trisciuoglio
Communauté

aws-lambda-java-integration

Provides AWS Lambda integration patterns for Java with cold start optimization. Use when deploying Java functions to AWS Lambda, choosing between Micronaut and Raw Java approaches, optimizing cold starts below 1 second, configuring API Gateway or ALB integration, or implementing serverless Java applications. Triggers include "create lambda java", "deploy java lambda", "micronaut lambda aws", "java lambda cold start", "aws lambda java performance", "java serverless framework".

installations
5
GitHub Stars
337
Mis à jour
18 août
giuseppe-trisciuoglio
Communauté

aws-lambda-typescript-integration

Provides AWS Lambda integration patterns for TypeScript with cold start optimization. Use when creating or deploying TypeScript Lambda functions, choosing between NestJS framework and raw TypeScript approaches, optimizing cold starts, configuring API Gateway or ALB integration, or implementing serverless TypeScript applications. Triggers include "create lambda typescript", "deploy typescript lambda", "nestjs lambda aws", "raw typescript lambda", "aws lambda typescript performance".

installations
5
GitHub Stars
337
Mis à jour
18 août
giuseppe-trisciuoglio
Communauté

aws-sdk-java-v2-s3

Provides Amazon S3 patterns and examples using AWS SDK for Java 2.x. Use when working with S3 buckets, uploading/downloading objects, multipart uploads, presigned URLs, S3 Transfer Manager, object operations, or S3-specific configurations.

installations
5
GitHub Stars
337
Mis à jour
18 août