При использовании OAuth 2 пути REST API из списка не требующих авторизацию требуют токен

У меня есть такой конфиг для Spring Security с OAuth 2. Мне нужно, чтобы пути /actuator и /api/v1/client/register были доступны без авторизации. Как это сделать? Фильтр с @Order(2) не дает доступ к этим путям, они по-прежнему требуют авторизацию при помощи OAuth 2 токена. Как исправить проблему?

Проблема, как я понимаю, в настройках, которые применяет OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)

@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration {

    @Value("${yandex.security.client-id}")
    private String clientId;

    @Value("${yandex.security.client-secret}")
    private String clientSecret;

    @Autowired
    private ClientRepository clients;

    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

        return http.build();
    }

    @Bean
    @Order(2)
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers("/actuator/**").permitAll()
                        .requestMatchers("/api/v1/client/register").permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer((oauth) -> oauth.jwt(Customizer.withDefaults()));

        return http.build();
    }

    @Bean
    public RegisteredClientRepository registeredClientRepository() {

        List<RegisteredClient> registeredClients = clients.findAll().stream()
                .map(client -> {
                    return  RegisteredClient.withId(UUID.randomUUID().toString())
                            .clientId(client.getClientId())
                            .clientSecret(client.getClientSecret())
                            .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
                            .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                            .scope("read")
                            .scope("write")
                            .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
                            .tokenSettings(TokenSettings.builder()
                                    .accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)
                                    .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256)
                                    .accessTokenTimeToLive(Duration.ofSeconds(30 * 60))
                                    .refreshTokenTimeToLive(Duration.ofSeconds(60 * 60))
                                    .reuseRefreshTokens(true)
                                    .build())
                            .build();
        }).toList();

        return new InMemoryRegisteredClientRepository(registeredClients);
    }

    /*@Bean
    public JdbcRegisteredClientRepository registeredClientRepository(JdbcTemplate jdbc) {
        JdbcRegisteredClientRepository clientRepository = new JdbcRegisteredClientRepository(jdbc);

        List<RegisteredClient> registeredClients = clients.findAll().stream()
                .map(client -> {
                    return RegisteredClient.withId(UUID.randomUUID().toString())
                            .clientId(client.getClientId())
                            .clientSecret(client.getClientSecret())
                            .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
                            .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                            .scope("read")
                            .scope("write")
                            .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
                            .tokenSettings(TokenSettings.builder()
                                    .accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)
                                    .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256)
                                    .accessTokenTimeToLive(Duration.ofSeconds(30 * 60))
                                    .refreshTokenTimeToLive(Duration.ofSeconds(60 * 60))
                                    .reuseRefreshTokens(true)
                                    .build())
                            .build();
                })
                .toList();

        registeredClients.forEach(clientRepository::save);

        return clientRepository;
    }*/

    @Bean
    public JWKSource<SecurityContext> jwkSource() {
        KeyPair keyPair = generateRsaKey();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAKey rsaKey = new RSAKey.Builder(publicKey)
                .privateKey(privateKey)
                .keyID(UUID.randomUUID().toString())
                .build();
        JWKSet jwkSet = new JWKSet(rsaKey);
        return new ImmutableJWKSet<>(jwkSet);
    }

    private static KeyPair generateRsaKey() {
        KeyPair keyPair;
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            keyPair = keyPairGenerator.generateKeyPair();
        }
        catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
        return keyPair;
    }

    @Bean
    public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
        return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
    }

    @Bean
    public AuthorizationServerSettings authorizationServerSettings() {
        return AuthorizationServerSettings.builder()
                .tokenEndpoint("/security/oauth/token")
                .build();
    }
}

Ответы (0 шт):