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.
@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!
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
orAfterInvocationProvider
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.
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!):combined with:
I feel that there is some magic glue missing from samples and/or docs to re-enable a perfectly working app after upgrading.
PS: if you're reading this later, please be advised that for all the permitted routes we either filter external traffic for that!