Summary
I am working with Keycloak . all "Get" request are working fine i.e @GetMapping("/") in resource microservice.
But "@Postmapping(/add)" incontroller and try to consume from home.html or index.html, am issue. 403 forbidden. CSRF Token has been associated to this clientCSRF
Actual Behavior
When i tried to consume @PostMapping("/message") issue. 403 forbidden.
Expected Behavior
Expecting successful @PostMapping("/message") consumption and return message.
Configuration
In Resource microservice
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
http.authorizeRequests().anyRequest().authenticated();
http.headers().frameOptions().sameOrigin();
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new KeycloakRealmRoleConverter());
return jwtAuthenticationConverter;
}
@Bean
public JwtDecoder jwtDecoderByIssuerUri(OAuth2ResourceServerProperties properties) {
String issuerUri = properties.getJwt().getIssuerUri();
NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) JwtDecoders.fromIssuerLocation(issuerUri);
jwtDecoder.setClaimSetConverter(new UsernameSubClaimAdapter());
return jwtDecoder;
}
}
class UsernameSubClaimAdapter implements Converter<Map<String, Object>, Map<String, Object>> {
private final MappedJwtClaimSetConverter delegate = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap());
@Override
public Map<String, Object> convert(Map<String, Object> claims) {
Map<String, Object> convertedClaims = this.delegate.convert(claims);
String username = (String) convertedClaims.get("preferred_username");
convertedClaims.put("sub", username);
return convertedClaims;
}
}
class KeycloakRealmRoleConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
@Override
@SuppressWarnings("unchecked")
public Collection<GrantedAuthority> convert(final Jwt jwt) {
final Map<String, Object> realmAccess = (Map<String, Object>) jwt.getClaims().get("realm_access");
return ((List<String>) realmAccess.get("roles")).stream()
.map(roleName -> "ROLE_" + roleName)
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
}
In controller
@SpringBootApplication
@Controller
public class HotelsApplication {
public static void main(String[] args) {
SpringApplication.run(HotelsApplication.class, args);
}
@GetMapping("/whoami")
@ResponseBody
public Authentication whoami(Authentication auth) {
return auth;
}
/* newly added post method
* which is not working as expected , it sis ending up with error
* Failed to load resource: the server responded with a status of 403 (Forbidden)
*/
@PostMapping("/message")
public String createMessage(@RequestBody String message) {
return String.format("Message was created. Content: %s", message);
}
}
Yml file
server:
port: 8081
spring:
application:
name: sample-service
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:8090/auth/realms/spring-cloud-realm
Version
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
<springBootVersion>2.2.4.RELEASE</springBootVersion>
Sample
Comment From: eleftherias
Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.
Comment From: eleftherias
This is intentional behaviour intended to protect the application from CSRF attacks. You can learn more about CSRF in the documentation.
Comment From: ayouway
http.csrf().disable()