View Javadoc
1   /*
2    * Copyright (c) 2024 Kaiserpfalz EDV-Service, Roland T. Lichti
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 3 of the License, or (at your option) any later version.
8    * 
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   * 
14   * You should have received a copy of the GNU Lesser General Public License
15   * along with this program; if not, write to the Free Software Foundation,
16   * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17   */
18  package de.kaiserpfalzedv.commons.spring.security;
19  
20  
21  
22  import org.springframework.http.ResponseEntity;
23  import org.springframework.security.core.Authentication;
24  import org.springframework.security.oauth2.core.oidc.user.OidcUser;
25  import org.springframework.security.web.authentication.logout.LogoutHandler;
26  import org.springframework.stereotype.Component;
27  import org.springframework.web.client.RestTemplate;
28  import org.springframework.web.util.UriComponentsBuilder;
29  
30  import jakarta.servlet.http.HttpServletRequest;
31  import jakarta.servlet.http.HttpServletResponse;
32  import lombok.extern.slf4j.Slf4j;
33  
34  
35  /**
36   * 
37   * @author klenkes74 {@literal <rlichti@kaiserpfalz-edv.de>}
38   * @version 1.0.0
39   * @since 2024-06-14
40   */
41  @Component
42  @Slf4j
43  public class KeycloakLogoutHandler implements LogoutHandler {
44      private final RestTemplate restTemplate;
45  
46      public KeycloakLogoutHandler(RestTemplate restTemplate) {
47          this.restTemplate = restTemplate;
48      }
49  
50      @Override
51      public void logout(HttpServletRequest request, HttpServletResponse response, Authentication auth) {
52          logoutFromKeycloak((OidcUser) auth.getPrincipal());
53      }
54  
55      private void logoutFromKeycloak(OidcUser user) {
56          String endSessionEndpoint = user.getIssuer() + "/protocol/openid-connect/logout";
57          UriComponentsBuilder builder = UriComponentsBuilder
58              .fromUriString(endSessionEndpoint)
59              .queryParam("id_token_hint", user.getIdToken().getTokenValue());
60  
61          ResponseEntity<String> logoutResponse = restTemplate.getForEntity(
62          builder.toUriString(), String.class);
63          if (logoutResponse.getStatusCode().is2xxSuccessful()) {
64              log.info("Successfully logged out from Keycloak");
65          } else {
66              log.error("Could not propagate logout to Keycloak");
67          }
68      }
69  }