package org.pac4j.cas.client.rest; import org.jasig.cas.client.authentication.AttributePrincipal; import org.jasig.cas.client.validation.Assertion; import org.jasig.cas.client.validation.TicketValidationException; import org.pac4j.cas.config.CasConfiguration; import org.pac4j.cas.profile.CasProfile; import org.pac4j.cas.profile.CasRestProfile; import org.pac4j.cas.util.HttpUtils; import org.pac4j.core.client.DirectClient; import org.pac4j.core.context.HttpConstants; import org.pac4j.core.context.WebContext; import org.pac4j.core.credentials.TokenCredentials; import org.pac4j.core.exception.TechnicalException; import org.pac4j.core.credentials.UsernamePasswordCredentials; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; /** * This is {@link CasRestFormClient} able to communicate to * a CAS server via its REST api, to retrieve TGTs and STs * and to construct CAS principals. * * @author Misagh Moayyed * @since 1.8.0 */ public abstract class AbstractCasRestClient extends DirectClient<UsernamePasswordCredentials, CasRestProfile> { protected CasConfiguration configuration; public void destroyTicketGrantingTicket(final CasRestProfile profile, final WebContext context) { HttpURLConnection connection = null; try { final URL endpointURL = new URL(configuration.computeFinalRestUrl(context)); final URL deleteURL = new URL(endpointURL, endpointURL.getPath() + "/" + profile.getTicketGrantingTicketId()); connection = HttpUtils.openDeleteConnection(deleteURL); final int responseCode = connection.getResponseCode(); if (responseCode != HttpConstants.OK) { throw new TechnicalException("TGT delete request for `" + profile + "` failed: " + HttpUtils.buildHttpErrorMessage(connection)); } } catch (final IOException e) { throw new TechnicalException(e); } finally { HttpUtils.closeConnection(connection); } } public TokenCredentials requestServiceTicket(final String serviceURL, final CasRestProfile profile, final WebContext context) { HttpURLConnection connection = null; try { final URL endpointURL = new URL(configuration.computeFinalRestUrl(context)); final URL ticketURL = new URL(endpointURL, endpointURL.getPath() + "/" + profile.getTicketGrantingTicketId()); connection = HttpUtils.openPostConnection(ticketURL); final String payload = HttpUtils.encodeQueryParam("service", serviceURL); final BufferedWriter out = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), HttpConstants.UTF8_ENCODING)); out.write(payload); out.close(); final int responseCode = connection.getResponseCode(); if (responseCode == HttpConstants.OK) { try (final BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), HttpConstants.UTF8_ENCODING))) { return new TokenCredentials(in.readLine(), getClass().getSimpleName()); } } throw new TechnicalException("Service ticket request for `" + profile + "` failed: " + HttpUtils.buildHttpErrorMessage(connection)); } catch (final IOException e) { throw new TechnicalException(e); } finally { HttpUtils.closeConnection(connection); } } public CasProfile validateServiceTicket(final String serviceURL, final TokenCredentials ticket, final WebContext context) { try { final Assertion assertion = configuration.retrieveTicketValidator(context).validate(ticket.getToken(), serviceURL); final AttributePrincipal principal = assertion.getPrincipal(); final CasProfile casProfile = new CasProfile(); casProfile.setId(principal.getName()); casProfile.addAttributes(principal.getAttributes()); return casProfile; } catch (final TicketValidationException e) { throw new TechnicalException(e); } } public CasConfiguration getConfiguration() { return configuration; } public void setConfiguration(final CasConfiguration configuration) { this.configuration = configuration; } }