package org.apereo.cas.support.openid.web.flow; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.CasProtocolConstants; import org.apereo.cas.authentication.Credential; import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy; import org.apereo.cas.authentication.principal.Principal; import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.support.openid.OpenIdProtocolConstants; import org.apereo.cas.support.openid.authentication.principal.OpenIdCredential; import org.apereo.cas.support.openid.authentication.principal.OpenIdService; import org.apereo.cas.support.openid.web.support.DefaultOpenIdUserNameExtractor; import org.apereo.cas.support.openid.web.support.OpenIdUserNameExtractor; import org.apereo.cas.ticket.registry.TicketRegistrySupport; import org.apereo.cas.web.flow.AbstractNonInteractiveCredentialsAction; import org.apereo.cas.web.flow.resolver.CasDelegatingWebflowEventResolver; import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver; import org.apereo.cas.web.support.WebUtils; import org.springframework.webflow.execution.RequestContext; /** * Attempts to utilize an existing single sign on session, but only if the * Principal of the existing session matches the new Principal. Note that care * should be taken when using credentials that are automatically provided and * not entered by the user. * * @author Scott Battaglia * @since 3.1 */ public class OpenIdSingleSignOnAction extends AbstractNonInteractiveCredentialsAction { private OpenIdUserNameExtractor extractor = new DefaultOpenIdUserNameExtractor(); private final TicketRegistrySupport ticketRegistrySupport; public OpenIdSingleSignOnAction(final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver, final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver, final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy, final OpenIdUserNameExtractor extractor, final TicketRegistrySupport ticketRegistrySupport) { super(initialAuthenticationAttemptWebflowEventResolver, serviceTicketRequestWebflowEventResolver, adaptiveAuthenticationPolicy); this.extractor = extractor; this.ticketRegistrySupport = ticketRegistrySupport; } @Override protected Credential constructCredentialsFromRequest(final RequestContext context) { final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context); final String openidIdentityParameter = context.getRequestParameters().get(OpenIdProtocolConstants.OPENID_IDENTITY); final String userName = getOpenIdSelectedIdentifier(context, ticketGrantingTicketId, openidIdentityParameter); final Service service = WebUtils.getService(context); // clear the service because otherwise we can fake the username if (service instanceof OpenIdService && StringUtils.isBlank(userName)) { context.getFlowScope().remove(CasProtocolConstants.PARAMETER_SERVICE); } if (StringUtils.isBlank(ticketGrantingTicketId) || StringUtils.isBlank(userName)) { return null; } return new OpenIdCredential(ticketGrantingTicketId, userName); } private String getOpenIdSelectedIdentifier(final RequestContext context, final String ticketGrantingTicketId, final String openidIdentityParameter) { if (OpenIdProtocolConstants.OPENID_IDENTIFIERSELECT.equals(openidIdentityParameter)) { context.getFlowScope().remove(OpenIdProtocolConstants.OPENID_LOCALID); final Principal p = ticketRegistrySupport.getAuthenticatedPrincipalFrom(ticketGrantingTicketId); if (p != null) { return p.getId(); } return OpenIdProtocolConstants.OPENID_IDENTIFIERSELECT; } final String userName = this.extractor.extractLocalUsernameFromUri(openidIdentityParameter); context.getFlowScope().put(OpenIdProtocolConstants.OPENID_LOCALID, userName); return userName; } }