Skip to content

Commit

Permalink
Merge branch 'jacekkow-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
XSmeets committed Aug 17, 2024
2 parents b641f9d + 7ad5493 commit eaffa08
Show file tree
Hide file tree
Showing 18 changed files with 391 additions and 49 deletions.
2 changes: 2 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github: [jacekkow]
buy_me_a_coffee: jacekkow
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ The following CAS features are currently implemented:

The following features are **missing**:
* SAML request/response [CAS 3.0 - optional]
* Proxy ticket service and proxy ticket validation [CAS 2.0]

The following features are out of scope:
* Long-Term Tickets - Remember-Me [CAS 3.0 - optional]
Expand All @@ -33,7 +32,7 @@ As a rule of thumb plugin version should **match your Keycloak version**.
Quarkus is the default distribution method of Keycloak 17.0.0 and newer. For legacy installations using WildFly, please refer to the [old README](https://github.com/jacekkow/keycloak-protocol-cas/blob/16.1.1/README.md).

1. Download the latest release compatible with your Keycloak version from the [releases page](https://github.com/jacekkow/keycloak-protocol-cas/releases).
2. Put the downloaded JAR file into the `providers/` directory inside Keycloak installation folder.
2. Put the downloaded JAR file into the `providers/` directory inside Keycloak installation folder. If necessary, adjust the permissions/ownership so that the user Keycloak runs as is able to read this file.
3. Stop the Keycloak server.
4. (Re-)build the installation using `kc.sh build` command.
5. Start the Keycloak: `kc.sh start`
Expand Down
15 changes: 11 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

<groupId>org.keycloak</groupId>
<artifactId>keycloak-protocol-cas</artifactId>
<version>24.0.4</version>
<version>25.0.2</version>
<name>Keycloak CAS Protocol</name>
<description />

Expand All @@ -32,10 +32,11 @@
<jboss.logging.version>3.5.3.Final</jboss.logging.version>
<jboss.logging.tools.version>2.2.1.Final</jboss.logging.tools.version>
<junit.version>4.13.2</junit.version>
<resteasy.version>6.2.7.Final</resteasy.version>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
<project.build.outputTimestamp>1715158027</project.build.outputTimestamp>
<project.build.outputTimestamp>1721292433</project.build.outputTimestamp>
</properties>

<dependencies>
Expand Down Expand Up @@ -64,6 +65,12 @@
<version>${apache.httpcomponents.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core-spi</artifactId>
<version>${resteasy.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
Expand Down Expand Up @@ -117,13 +124,13 @@
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>3.1.6</version>
<version>3.1.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<version>5.12.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
31 changes: 20 additions & 11 deletions src/main/java/org/keycloak/protocol/cas/CASLoginProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import org.apache.http.HttpEntity;
import org.jboss.logging.Logger;
import org.keycloak.common.util.KeycloakUriBuilder;
import org.keycloak.common.util.Time;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.*;
import org.keycloak.protocol.ClientData;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.cas.endpoints.AbstractValidateEndpoint;
import org.keycloak.protocol.cas.utils.LogoutHelper;
import org.keycloak.protocol.cas.utils.UserMapperHelper;
import org.keycloak.protocol.oidc.utils.OAuth2Code;
Expand All @@ -23,7 +24,6 @@

import java.io.IOException;
import java.net.URI;
import java.util.UUID;

public class CASLoginProtocol implements LoginProtocol {
private static final Logger logger = Logger.getLogger(CASLoginProtocol.class);
Expand All @@ -36,11 +36,17 @@ public class CASLoginProtocol implements LoginProtocol {
public static final String GATEWAY_PARAM = "gateway";
public static final String TICKET_PARAM = "ticket";
public static final String FORMAT_PARAM = "format";
public static final String PGTURL_PARAM = "pgtUrl";
public static final String TARGET_SERVICE_PARAM = "targetService";
public static final String PGT_PARAM = "pgt";

public static final String TICKET_RESPONSE_PARAM = "ticket";
public static final String SAMLART_RESPONSE_PARAM = "SAMLart";

public static final String SERVICE_TICKET_PREFIX = "ST-";
public static final String PROXY_GRANTING_TICKET_IOU_PREFIX = "PGTIOU-";
public static final String PROXY_GRANTING_TICKET_PREFIX = "PGT-";
public static final String PROXY_TICKET_PREFIX = "PT-";
public static final String SESSION_SERVICE_TICKET = "service_ticket";

public static final String LOGOUT_REDIRECT_URI = "CAS_LOGOUT_REDIRECT_URI";
Expand Down Expand Up @@ -104,15 +110,9 @@ public Response authenticated(AuthenticationSessionModel authSession, UserSessio
String service = authSession.getRedirectUri();
//TODO validate service

OAuth2Code codeData = new OAuth2Code(UUID.randomUUID().toString(),
Time.currentTime() + userSession.getRealm().getAccessCodeLifespan(),
null, null, authSession.getRedirectUri(), null, null,
userSession.getId());
String code = OAuth2CodeParser.persistCode(session, clientSession, codeData);

KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(service);

String loginTicket = SERVICE_TICKET_PREFIX + code;
String loginTicket = AbstractValidateEndpoint.getST(session, clientSession, service);

if (authSession.getClientNotes().containsKey(CASLoginProtocol.TARGET_PARAM)) {
// This was a SAML 1.1 auth request so return the ticket ID as "SAMLart" instead of "ticket"
Expand All @@ -137,6 +137,16 @@ public Response sendError(AuthenticationSessionModel authSession, Error error) {
return ErrorPage.error(session, authSession, Response.Status.INTERNAL_SERVER_ERROR, error.name());
}

@Override
public ClientData getClientData(AuthenticationSessionModel authSession) {
return new ClientData(authSession.getRedirectUri(), null, null, null);
}

@Override
public Response sendError(ClientModel clientModel, ClientData clientData, Error error) {
return null;
}

@Override
public Response backchannelLogout(UserSessionModel userSession, AuthenticatedClientSessionModel clientSession) {
String logoutUrl = clientSession.getRedirectUri();
Expand All @@ -146,8 +156,7 @@ public Response backchannelLogout(UserSessionModel userSession, AuthenticatedCli
sendSingleLogoutRequest(logoutUrl, serviceTicket);
}
ClientModel client = clientSession.getClient();
new ResourceAdminManager(session).logoutClientSession(realm, client, clientSession).close();
return Response.ok().build();
return new ResourceAdminManager(session).logoutClientSession(realm, client, clientSession);
}

private void sendSingleLogoutRequest(String logoutUrl, String serviceTicket) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.keycloak.protocol.cas;

import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;

import org.keycloak.events.EventBuilder;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
Expand Down Expand Up @@ -51,13 +51,12 @@ public Object serviceValidate() {

@Path("proxyValidate")
public Object proxyValidate() {
//TODO implement
return serviceValidate();
return new ProxyValidateEndpoint(session, realm, event);
}

@Path("proxy")
public Object proxy() {
return Response.serverError().entity("Not implemented").build();
return new ProxyEndpoint(session, realm, event);
}

@Path("p3/serviceValidate")
Expand Down
Loading

0 comments on commit eaffa08

Please sign in to comment.