Je configure une instance Keycloak pour qu'elle fonctionne avec l'application Spring Boot avec la sécurité Spring incluse. J'utilise postman pour tester le service. Je commence par obtenir un nouveau jeton d'accès et cela fonctionne bien. Lorsque je fais un appel HTTP GET au point de terminaison sécurisé - tout se passe bien, le personnel est renvoyé. Mais lorsque je fais un appel HTTP POST / PUT / DELETE au point de terminaison sécurisé Keycloak dit Erreur 403 Interdit. Jetez un œil et dites-moi ce qui ne va pas.
J'ai déjà testé l'option http.csrf (). disable (), puis fonctionne correctement, mais ce n'est pas la solution pour la production.
SecurityConfig.java
2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:1080/api/my-endpoint 2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /api/my-endpoint 2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler : AuthenticatedActionsValve.invoke http://localhost:1080/api/my-endpoint 2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler : Policy enforcement is disabled. 2019-04-01 14:04:54.742 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:1080/error 2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Request is to process authentication 2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication 2019-04-01 14:04:54.743 TRACE 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator : --> authenticate() 2019-04-01 14:04:54.743 TRACE 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator : try bearer 2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator : Found [1] values in authorization header, selecting the first value for Bearer. 2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator : Verifying access_token 2019-04-01 14:04:54.743 TRACE 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator : access_token: eyJhbs...blablab....signature 2019-04-01 14:04:54.744 DEBUG 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator : successful authorized 2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] o.k.a.RefreshableKeycloakSecurityContext : checking whether to refresh. 2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] org.keycloak.adapters.AdapterUtils : useResourceRoleMappings 2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] org.keycloak.adapters.AdapterUtils : Setting roles: 2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] org.keycloak.adapters.AdapterUtils : role: my_admin 2019-04-01 14:04:54.744 DEBUG 2952 --- [io-1080-exec-10] a.s.a.SpringSecurityRequestAuthenticator : Completing bearer authentication. Bearer roles: [my_admin] 2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator : User 'my_user' invoking 'http://localhost:1080/error' on client 'myclient' 2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator : Bearer AUTHENTICATED 2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Auth outcome: AUTHENTICATED 2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@fb0506b7: Principal: my_user; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@ecf147d; Granted Authorities: ROLE_my_admin 2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler : AuthenticatedActionsValve.invoke http://localhost:1080/error 2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler : Policy enforcement is disabled.
application.yml:
keycloak: auth-server-url: http://localhost:11080/auth realm: myrealm resource: myclient public-client: true principal-attribute: preferred_username ssl-required: external use-resource-role-mappings: true
Quelques journaux de l'application (niveau du journal de trace keycloak):
@Configuration @EnableWebSecurity @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class) class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } @Bean public KeycloakSpringBootConfigResolver KeycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http .authorizeRequests() .antMatchers( "/api/**").hasRole("my_admin") .anyRequest().permitAll(); }
3 Réponses :
Il s'agit d'une protection CSRF fournie par Spring Security. Avez-vous vraiment besoin de cette protection avec le jeton Keycloak? Le token est uniquement inclus dans le cookie ou est-il également présent dans l'en-tête Authorization?
Le jeton d'identité est stocké dans les cookies, le jeton d'accès est transmis dans l'en-tête
Si le jeton d'accès est passé dans l'en-tête, vous n'avez pas besoin de jeton CSRF. Il semble que vous utilisiez Spring Boot avec Spring Security et un adaptateur keycloak: n'oubliez pas de désactiver les 4 filtres fournis par l'adaptateur keycloak car ils sont automatiquement enregistrés par Spring boot.
J'ai découvert que je n'avais pas utilisé de jeton CSRF dans les requêtes ajax. Spring Security active automatiquement la protection CSRF. Le jeton CSRF est automatiquement généré pour le premier appel du service Web et a une portée de session. Vous devez enregistrer ce jeton dans la balise Meta. Il est nécessaire d'inclure un jeton CSRF à chaque requête non-GET (les requêtes GET ne sont pas nécessaires pour être protégées avec un jeton CSRF, car elles sont conçues pour ne pas modifier les appels d'API).
Solution: il suffit d'inclure cette ligne dans l'en-tête de la page html (thymeleaf):
et utilisez-le dans l'appel ajax dans l'en-tête:
en-têtes: {
'X-CSRF-TOKEN': $ ('#_ csrf'). Attr ('contenu')
},
vous devriez faire deux configurations suivantes:
http.csrf (). disable ()
Je n'ai eu qu'à désactiver CSRF pour résoudre ce problème, mais est-ce que je peux désactiver CSRF?
Si vous configurez la protection CSRF, votre client doit également envoyer le jeton CSRF. Si vous ne le faites pas du facteur, cela échouera.