package org.apereo.cas.support.oauth.web.response.accesstoken.ext;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.authentication.Authentication;
import org.apereo.cas.authentication.AuthenticationResult;
import org.apereo.cas.authentication.DefaultAuthenticationResult;
import org.apereo.cas.authentication.principal.Service;
import org.apereo.cas.configuration.model.support.oauth.OAuthProperties;
import org.apereo.cas.services.RegisteredServiceAccessStrategyUtils;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.services.UnauthorizedServiceException;
import org.apereo.cas.support.oauth.OAuth20Constants;
import org.apereo.cas.support.oauth.OAuth20GrantTypes;
import org.apereo.cas.support.oauth.authenticator.OAuth20CasAuthenticationBuilder;
import org.apereo.cas.support.oauth.profile.OAuthUserProfile;
import org.apereo.cas.support.oauth.services.OAuthRegisteredService;
import org.apereo.cas.support.oauth.util.OAuth20Utils;
import org.apereo.cas.ticket.TicketGrantingTicket;
import org.apereo.cas.ticket.registry.TicketRegistry;
import org.apereo.cas.web.support.WebUtils;
import org.pac4j.core.context.J2EContext;
import org.pac4j.core.profile.ProfileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;
/**
* This is {@link AccessTokenPasswordGrantRequestExtractor}.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
public class AccessTokenPasswordGrantRequestExtractor extends BaseAccessTokenGrantRequestExtractor {
private static final Logger LOGGER = LoggerFactory.getLogger(AccessTokenPasswordGrantRequestExtractor.class);
private final OAuth20CasAuthenticationBuilder authenticationBuilder;
public AccessTokenPasswordGrantRequestExtractor(final ServicesManager servicesManager,
final TicketRegistry ticketRegistry,
final HttpServletRequest request,
final HttpServletResponse response,
final OAuth20CasAuthenticationBuilder authenticationBuilder,
final CentralAuthenticationService centralAuthenticationService,
final OAuthProperties oAuthProperties) {
super(servicesManager, ticketRegistry, request, response, centralAuthenticationService, oAuthProperties);
this.authenticationBuilder = authenticationBuilder;
}
@Override
public AccessTokenRequestDataHolder extract() {
final String clientId = request.getParameter(OAuth20Constants.CLIENT_ID);
LOGGER.debug("Locating OAuth registered service by client id [{}]", clientId);
final OAuthRegisteredService registeredService = OAuth20Utils.getRegisteredOAuthService(this.servicesManager, clientId);
LOGGER.debug("Located OAuth registered service [{}]", registeredService);
final J2EContext context = WebUtils.getPac4jJ2EContext(request, response);
final ProfileManager manager = WebUtils.getPac4jProfileManager(request, response);
final Optional<OAuthUserProfile> profile = manager.get(true);
if (!profile.isPresent()) {
throw new UnauthorizedServiceException("OAuth user profile cannot be determined");
}
LOGGER.debug("Creating matching service request based on [{}]", registeredService);
final boolean requireServiceHeader = oAuthProperties.getGrants().getResourceOwner().isRequireServiceHeader();
if (requireServiceHeader) {
LOGGER.debug("Using request headers to identify and build the target service url");
}
final Service service = this.authenticationBuilder.buildService(registeredService, context, requireServiceHeader);
LOGGER.debug("Authenticating the OAuth request indicated by [{}]", service);
final Authentication authentication = this.authenticationBuilder.build(profile.get(), registeredService, context, service);
RegisteredServiceAccessStrategyUtils.ensurePrincipalAccessIsAllowedForService(service, registeredService, authentication);
final AuthenticationResult result = new DefaultAuthenticationResult(authentication, requireServiceHeader ? service : null);
final TicketGrantingTicket ticketGrantingTicket = this.centralAuthenticationService.createTicketGrantingTicket(result);
return new AccessTokenRequestDataHolder(service, authentication, registeredService, ticketGrantingTicket);
}
@Override
public boolean supports(final HttpServletRequest context) {
final String grantType = context.getParameter(OAuth20Constants.GRANT_TYPE);
return OAuth20Utils.isGrantType(grantType, OAuth20GrantTypes.PASSWORD);
}
}