Search in sources :

Example 1 with CasServiceTicketValidatedEvent

use of org.apereo.cas.support.events.ticket.CasServiceTicketValidatedEvent in project cas by apereo.

the class DefaultCentralAuthenticationService method validateServiceTicket.

@Audit(action = AuditableActions.SERVICE_TICKET_VALIDATE, actionResolverName = AuditActionResolvers.VALIDATE_SERVICE_TICKET_RESOLVER, resourceResolverName = AuditResourceResolvers.VALIDATE_SERVICE_TICKET_RESOURCE_RESOLVER)
@Override
public Assertion validateServiceTicket(final String serviceTicketId, final Service service) throws AbstractTicketException {
    if (!isTicketAuthenticityVerified(serviceTicketId)) {
        LOGGER.info("Service ticket [{}] is not a valid ticket issued by CAS.", serviceTicketId);
        throw new InvalidTicketException(serviceTicketId);
    }
    val serviceTicket = configurationContext.getTicketRegistry().getTicket(serviceTicketId, ServiceTicket.class);
    if (serviceTicket == null) {
        LOGGER.warn("Service ticket [{}] does not exist.", serviceTicketId);
        throw new InvalidTicketException(serviceTicketId);
    }
    try {
        val selectedService = resolveServiceFromAuthenticationRequest(serviceTicket.getService());
        val resolvedService = resolveServiceFromAuthenticationRequest(service);
        LOGGER.debug("Resolved service [{}] from the authentication request with service [{}] linked to service ticket [{}]", resolvedService, selectedService, serviceTicket.getId());
        configurationContext.getLockRepository().execute(serviceTicket.getId(), Unchecked.supplier(() -> {
            if (serviceTicket.isExpired()) {
                LOGGER.info("ServiceTicket [{}] has expired.", serviceTicketId);
                throw new InvalidTicketException(serviceTicketId);
            }
            if (!configurationContext.getServiceMatchingStrategy().matches(selectedService, resolvedService)) {
                LOGGER.error("Service ticket [{}] with service [{}] does not match supplied service [{}]", serviceTicketId, serviceTicket.getService().getId(), resolvedService.getId());
                throw new UnrecognizableServiceForServiceTicketValidationException(selectedService);
            }
            serviceTicket.update();
            configurationContext.getTicketRegistry().updateTicket(serviceTicket);
            return serviceTicket;
        }));
        val registeredService = configurationContext.getServicesManager().findServiceBy(selectedService);
        LOGGER.trace("Located registered service definition [{}] from [{}] to handle validation request", registeredService, selectedService);
        RegisteredServiceAccessStrategyUtils.ensureServiceAccessIsAllowed(selectedService, registeredService);
        val root = serviceTicket.getTicketGrantingTicket().getRoot();
        val authentication = getAuthenticationSatisfiedByPolicy(root.getAuthentication(), new ServiceContext(selectedService, registeredService));
        val principal = authentication.getPrincipal();
        val attributePolicy = Objects.requireNonNull(registeredService.getAttributeReleasePolicy());
        LOGGER.debug("Attribute policy [{}] is associated with service [{}]", attributePolicy, registeredService);
        val context = RegisteredServiceAttributeReleasePolicyContext.builder().registeredService(registeredService).service(selectedService).principal(principal).build();
        val attributesToRelease = attributePolicy.getAttributes(context);
        LOGGER.debug("Calculated attributes for release per the release policy are [{}]", attributesToRelease.keySet());
        val principalId = registeredService.getUsernameAttributeProvider().resolveUsername(principal, selectedService, registeredService);
        val builder = DefaultAuthenticationBuilder.of(principal, configurationContext.getPrincipalFactory(), attributesToRelease, selectedService, registeredService, authentication);
        LOGGER.debug("Principal determined for release to [{}] is [{}]", registeredService.getServiceId(), principalId);
        builder.addAttribute(CasProtocolConstants.VALIDATION_CAS_MODEL_ATTRIBUTE_NAME_FROM_NEW_LOGIN, CollectionUtils.wrap(((RenewableServiceTicket) serviceTicket).isFromNewLogin()));
        builder.addAttribute(CasProtocolConstants.VALIDATION_REMEMBER_ME_ATTRIBUTE_NAME, CollectionUtils.wrap(CoreAuthenticationUtils.isRememberMeAuthentication(authentication)));
        val finalAuthentication = builder.build();
        val releasePolicyContext = RegisteredServiceAttributeReleasePolicyContext.builder().registeredService(registeredService).service(service).principal(principal).build();
        val policyAttributes = registeredService.getAttributeReleasePolicy().getAttributes(releasePolicyContext);
        val merger = CoreAuthenticationUtils.getAttributeMerger(PrincipalAttributesCoreProperties.MergingStrategyTypes.MULTIVALUED);
        var accessAttributes = CoreAuthenticationUtils.mergeAttributes(principal.getAttributes(), authentication.getAttributes(), merger);
        accessAttributes = CoreAuthenticationUtils.mergeAttributes(accessAttributes, finalAuthentication.getPrincipal().getAttributes(), merger);
        accessAttributes = CoreAuthenticationUtils.mergeAttributes(accessAttributes, finalAuthentication.getAttributes(), merger);
        accessAttributes = CoreAuthenticationUtils.mergeAttributes(accessAttributes, policyAttributes, merger);
        val accessPrincipal = configurationContext.getPrincipalFactory().createPrincipal(principal.getId(), accessAttributes);
        enforceRegisteredServiceAccess(selectedService, registeredService, accessPrincipal);
        AuthenticationCredentialsThreadLocalBinder.bindCurrent(finalAuthentication);
        val assertion = new DefaultAssertionBuilder(finalAuthentication).with(selectedService).with(serviceTicket.getTicketGrantingTicket().getChainedAuthentications()).with(((RenewableServiceTicket) serviceTicket).isFromNewLogin()).build();
        doPublishEvent(new CasServiceTicketValidatedEvent(this, serviceTicket, assertion));
        return assertion;
    } finally {
        FunctionUtils.doUnchecked(s -> {
            if (serviceTicket.isExpired()) {
                deleteTicket(serviceTicketId);
            } else {
                configurationContext.getTicketRegistry().updateTicket(serviceTicket);
            }
        });
    }
}
Also used : lombok.val(lombok.val) DefaultAssertionBuilder(org.apereo.cas.validation.DefaultAssertionBuilder) ServiceContext(org.apereo.cas.services.ServiceContext) CasServiceTicketValidatedEvent(org.apereo.cas.support.events.ticket.CasServiceTicketValidatedEvent) InvalidTicketException(org.apereo.cas.ticket.InvalidTicketException) UnrecognizableServiceForServiceTicketValidationException(org.apereo.cas.ticket.UnrecognizableServiceForServiceTicketValidationException) RenewableServiceTicket(org.apereo.cas.ticket.RenewableServiceTicket) Audit(org.apereo.inspektr.audit.annotation.Audit)

Aggregations

lombok.val (lombok.val)1 ServiceContext (org.apereo.cas.services.ServiceContext)1 CasServiceTicketValidatedEvent (org.apereo.cas.support.events.ticket.CasServiceTicketValidatedEvent)1 InvalidTicketException (org.apereo.cas.ticket.InvalidTicketException)1 RenewableServiceTicket (org.apereo.cas.ticket.RenewableServiceTicket)1 UnrecognizableServiceForServiceTicketValidationException (org.apereo.cas.ticket.UnrecognizableServiceForServiceTicketValidationException)1 DefaultAssertionBuilder (org.apereo.cas.validation.DefaultAssertionBuilder)1 Audit (org.apereo.inspektr.audit.annotation.Audit)1