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

Matthias Piepkorn
2017-02-05 5a0869a771f65f87fa2a4ed402fb1f3597b92198
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 import org.keycloak.saml.common.exceptions.ConfigurationException;
12 import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
13 import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
14
15 import javax.ws.rs.core.HttpHeaders;
16 import javax.xml.datatype.XMLGregorianCalendar;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.nio.charset.StandardCharsets;
20
21 public class LogoutHelper {
22     //although it looks alike, the CAS SLO protocol has nothing to do with SAML; so we build the format
23     //required by the spec manually
24     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" +
25             "  <saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">@NOT_USED@</saml:NameID>\n" +
26             "  <samlp:SessionIndex>$SESSION_IDENTIFIER</samlp:SessionIndex>\n" +
27             "</samlp:LogoutRequest>";
28
29     public static HttpEntity buildSingleLogoutRequest(String serviceTicket) {
30         String id = IDGenerator.create("ID_");
31         XMLGregorianCalendar issueInstant;
32         try {
33             issueInstant = XMLTimeUtil.getIssueInstant();
34         } catch (ConfigurationException e) {
35             throw new RuntimeException(e);
36         }
37         String document = TEMPLATE.replace("$ID", id).replace("$ISSUE_INSTANT", issueInstant.toString())
38                 .replace("$SESSION_IDENTIFIER", serviceTicket);
39         return new StringEntity(document, ContentType.APPLICATION_XML.withCharset(StandardCharsets.UTF_8));
40     }
41
42     public static void postWithRedirect(KeycloakSession session, String url, HttpEntity postBody) throws IOException {
43         HttpClient httpClient = session.getProvider(HttpClientProvider.class).getHttpClient();
44         for (int i = 0; i < 2; i++) { // follow redirects once
45             HttpPost post = new HttpPost(url);
46             post.setEntity(postBody);
47             HttpResponse response = httpClient.execute(post);
48             try {
49                 int status = response.getStatusLine().getStatusCode();
50                 if (status == 302 && !url.endsWith("/")) {
51                     String redirect = response.getFirstHeader(HttpHeaders.LOCATION).getValue();
52                     String withSlash = url + "/";
53                     if (withSlash.equals(redirect)) {
54                         url = withSlash;
55                         continue;
56                     }
57                 }
58             } finally {
59                 HttpEntity entity = response.getEntity();
60                 if (entity != null) {
61                     InputStream is = entity.getContent();
62                     if (is != null)
63                         is.close();
64                 }
65
66             }
67             break;
68         }
69     }
70 }