spring-projects / spring-projects/spring-security

Document how to upgrade to v6 with ACL

Open
#12,995 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage type: enhancement
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

Hi,

I think the documentation is lacking crucial information on how to proceed with ACL in spring-security-6. The aforementioned docs list either AccessDecisionVoter or AfterInvocationProvider to be implemented, both of which are deprecated though. The migration docs are of no help and the usual more helpful resource SO is not up to speed yet or might never be.

The ACL samples also got no update and I don't think they would actually just work out of the box, as all that's been done for the update was to bump versions.

To give more context to my personal problem, I implement a custom permission evaluator but neither AccessDecisionManager or AccessDecisionVoter.

    @Bean
    fun expressionHandler(): MethodSecurityExpressionHandler {
        val customPermissionEvaluator = CustomPermissionEvaluator(aclService())
        customPermissionEvaluator.setPermissionFactory(permissionFactory())

        val expressionHandler = DefaultMethodSecurityExpressionHandler()
        expressionHandler.setPermissionEvaluator(customPermissionEvaluator)

        return expressionHandler
    }

Other than that we populate some grants in an AuthenticationEventListener but nothing else. Here's the relevant filter chain (I updated to the DSL just now and really dig it!):

@Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        val customConverter = JwtAuthenticationConverter()
        customConverter.setJwtGrantedAuthoritiesConverter(
            KeycloakPermissionsConverter(workspaceName, permissionsClaimKey)
        )

        http {
            authorizeRequests {
                // anyone with a valid jwt can access endpoints
                // the token is validated by the custom jwt converter set below
                authorize(anyRequest, authenticated)
                authorize(GET, "/actuator", permitAll)
                authorize(GET, "/actuator/*", permitAll)
                authorize(GET, "/api-docs", permitAll)
                authorize(GET, "/api-docs.yaml", permitAll)
                // the following endpoint is secured by custom tokens and not keycloak
                // TODO: could also be handled by spring-security probably
                authorize(POST, "/api/v1/public/redacted/callbacks", permitAll)
            }

            // disable unused stuff
            anonymous { disable() }
            logout { disable() }

            // disable X-FRAME-OPTIONS: deny, especially for file downloads. has virtually no effect on other routes
            headers { frameOptions { disable() } }

            // enable cors
            cors { }

            // places custom filter *before* the anonymous auth filter in the spring security
            // filter chain ordering (see addFilter)
            addFilterBefore<BearerTokenAuthenticationFilter>(filterChainExceptionHandler)
            addFilterAt<BearerTokenAuthenticationFilter>(queryParameterTokenFilter)

            // configure tokens to be validated and converted to our internal authorization with workspace READ/ADMIN permissions
            oauth2ResourceServer { jwt { jwtAuthenticationConverter = customConverter } }
        }

        return http.build()
    }

combined with:

@Configuration
@EnableMethodSecurity

I feel that there is some magic glue missing from samples and/or docs to re-enable a perfectly working app after upgrading.

18:33:43.735 [Test worker] DEBUG org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor - Authorizing method invocation ReflectiveMethodInvocation: public redacted redactedService.findById(java.lang.Long) throws redactedNotFoundException,eu.do24.web.api.errors.UnauthorizedException,org.springframework.security.access.AccessDeniedException; target is of class [redactedService]
18:33:43.740 [Test worker] WARN  org.springframework.security.access.expression.DenyAllPermissionEvaluator - Denying user cd9f1f41-07f5-4cc1-be00-b871e6ca8c78 permission 'READ' on object redacted@1a0373a4

PS: if you're reading this later, please be advised that for all the permitted routes we either filter external traffic for that!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the servlet ACL documentation and the Spring Security 6 migration documentation, then compare the ACL samples linked in the issue. Reproduce the reported custom permission evaluator and method-security setup to identify the missing upgrade guidance. Done means the documentation and relevant samples clearly explain the supported v6 ACL configuration and migration path.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin, spring
Domain
documentation, security
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.