Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how to upgrade to v6 with ACL #12995

Open
ChristianSch opened this issue Apr 11, 2023 · 1 comment
Open

Document how to upgrade to v6 with ACL #12995

ChristianSch opened this issue Apr 11, 2023 · 1 comment
Labels
status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement

Comments

@ChristianSch
Copy link

ChristianSch commented Apr 11, 2023

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!

@ChristianSch ChristianSch added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Apr 11, 2023
@ChristianSch
Copy link
Author

Related #13088

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

1 participant