mirror of https://github.com/jacekkow/keycloak-protocol-cas

Jacek Kowalski
2022-03-23 b1ec309effa13b22df969c3835605f6614d00a66
commit | author | age
57a6c1 1 package org.keycloak.protocol.cas.utils;
MP 2
3 import org.apache.http.HttpEntity;
4 import org.apache.http.HttpResponse;
5 import org.apache.http.client.HttpClient;
6 import org.apache.http.client.methods.HttpPost;
7 import org.apache.http.entity.ContentType;
8 import org.apache.http.entity.StringEntity;
9 import org.keycloak.connections.httpclient.HttpClientProvider;
10 import org.keycloak.models.KeycloakSession;
11
12 import javax.ws.rs.core.HttpHeaders;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.nio.charset.StandardCharsets;
1293d5 16 import java.text.SimpleDateFormat;
MP 17 import java.util.Date;
18 import java.util.UUID;
57a6c1 19
MP 20 public class LogoutHelper {
21     //although it looks alike, the CAS SLO protocol has nothing to do with SAML; so we build the format
22     //required by the spec manually
23     private static final String TEMPLATE = "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"$ID\" Version=\"2.0\" IssueInstant=\"$ISSUE_INSTANT\">\n" +
24             "  <saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">@NOT_USED@</saml:NameID>\n" +
25             "  <samlp:SessionIndex>$SESSION_IDENTIFIER</samlp:SessionIndex>\n" +
26             "</samlp:LogoutRequest>";
27
28     public static HttpEntity buildSingleLogoutRequest(String serviceTicket) {
1293d5 29         String id = "ID_" + UUID.randomUUID().toString();
MP 30         String issueInstant = new SimpleDateFormat("yyyy-MM-dd'T'H:mm:ss").format(new Date());
31         String document = TEMPLATE.replace("$ID", id).replace("$ISSUE_INSTANT", issueInstant)
57a6c1 32                 .replace("$SESSION_IDENTIFIER", serviceTicket);
MP 33         return new StringEntity(document, ContentType.APPLICATION_XML.withCharset(StandardCharsets.UTF_8));
34     }
35
36     public static void postWithRedirect(KeycloakSession session, String url, HttpEntity postBody) throws IOException {
37         HttpClient httpClient = session.getProvider(HttpClientProvider.class).getHttpClient();
38         for (int i = 0; i < 2; i++) { // follow redirects once
39             HttpPost post = new HttpPost(url);
40             post.setEntity(postBody);
41             HttpResponse response = httpClient.execute(post);
42             try {
43                 int status = response.getStatusLine().getStatusCode();
44                 if (status == 302 && !url.endsWith("/")) {
45                     String redirect = response.getFirstHeader(HttpHeaders.LOCATION).getValue();
46                     String withSlash = url + "/";
47                     if (withSlash.equals(redirect)) {
48                         url = withSlash;
49                         continue;
50                     }
51                 }
52             } finally {
53                 HttpEntity entity = response.getEntity();
54                 if (entity != null) {
55                     InputStream is = entity.getContent();
56                     if (is != null)
57                         is.close();
58                 }
59
60             }
61             break;
62         }
63     }
64 }