Получаю ошибку 403 при попытке выполнить запрос с Bearer токеном в Spring Boot 3.4.2 + Keycloak 26.0.4
Пытаюсь настроить авторизацию в приложении Spring Boot, использующем Keycloak для аутентификации. Когда я отправляю GET-запрос с Bearer токеном, получаю ответ с ошибкой 403 (Forbidden). В настройках Spring Security разрешены только пользователи с ролью member, но почему-то запрос не проходит.
- Spring Boot - 3.4.3
- Keycloak - 26.0.4.
Maven (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
<checkstyle.version>7.8.1</checkstyle.version>
<jacoco.version>0.8.4</jacoco.version>
<testcontainers.version>1.18.3</testcontainers.version>
<jooq.version>3.18.3</jooq.version>
<postgresql.jdbc.version>42.6.0</postgresql.jdbc.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- OpenAPI 3 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi</artifactId>
<version>2.8.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Keycloak -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>26.0.4</version>
</dependency>
<!-- Springdoc OpenAPI для интеграции с Spring Boot -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Runtime library -->
<dependency>
<groupId>com.github.therapi</groupId>
<artifactId>therapi-runtime-javadoc</artifactId>
<version>0.15.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-maven-plugin</artifactId>
<version>1.4</version>
</plugin>
</plugins>
</build>
</project>
Spring Security Configuration
@Configuration
@EnableWebSecurity
public class SSOConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.cors(Customizer.withDefaults());
http.csrf(AbstractHttpConfigurer::disable);
http.authorizeHttpRequests(registry -> {
registry
.requestMatchers("/swagger-ui/**").permitAll()
.requestMatchers("/swagger-ui.html").permitAll()
.requestMatchers("/v3/api-docs/**").permitAll()
.requestMatchers("/user/register/exception").permitAll()
.requestMatchers(HttpMethod.GET).hasRole("member");
}).oauth2Login(Customizer.withDefaults());
return http.build();
}
}
application.properties
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://127.0.0.1:8080/realms/opposite
spring.security.oauth2.client.registration.keycloak.provider=keycloak
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.client-id=backend
spring.security.oauth2.client.registration.keycloak.client-secret=XXXX
spring.security.oauth2.client.registration.keycloak.scope=openid
Авторизация в Keycloak
curl -X POST --location "http://127.0.0.1:8080/realms/opposite/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'client_id=frontend&username=75051519551&password=9561&grant_type=password'
Полученный токен
{
"exp": 1742795683,
"iat": 1742795383,
"jti": "4ce57c6b-0269-456a-a081-1cc3c4dfeb94",
"iss": "http://127.0.0.1:8080/realms/opposite",
"aud": "frontend",
"sub": "be93a350-64fe-44a4-b102-ae1b1684e7cc",
"typ": "bearer",
"azp": "backend",
"sid": "1cdb16ec-f003-46ce-bd2a-baa1ef34c33a",
"acr": "1",
"allowed-origins": [
"/*"
],
"realm_access": {
"roles": [
"member"
]
},
"resource_access": {
"backend": {
"roles": [
"member"
]
},
"frontend": {
"roles": [
"member"
]
}
},
"scope": "email profile",
"email_verified": true,
"name": "Иван Иванов",
"preferred_username": "75051519551",
"given_name": "Иван",
"family_name": "Иванов",
"email": "[email protected]"
}
Запрос на backend*
curl -X GET --location "http://127.0.0.1:8081/api/treasure/v1/transaction?name=qw&offset=0&numberOfRows=10" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer XXX"
Получаю ответ с ошибкой 403 (Forbidden) при попытке выполнить запрос с Bearer токеном, даже несмотря на то, что роль member присутствует в токене. Я проверил, что токен корректен.