package org.apereo.cas.support.oauth.web.response.accesstoken.ext;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.configuration.model.support.oauth.OAuthProperties;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.support.oauth.OAuth20Constants;
import org.apereo.cas.support.oauth.OAuth20GrantTypes;
import org.apereo.cas.support.oauth.services.OAuthRegisteredService;
import org.apereo.cas.support.oauth.util.OAuth20Utils;
import org.apereo.cas.ticket.InvalidTicketException;
import org.apereo.cas.ticket.OAuthToken;
import org.apereo.cas.ticket.registry.TicketRegistry;
import org.apereo.cas.web.support.WebUtils;
import org.pac4j.core.profile.ProfileManager;
import org.pac4j.core.profile.UserProfile;
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 AccessTokenAuthorizationCodeGrantRequestExtractor}.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
public class AccessTokenAuthorizationCodeGrantRequestExtractor extends BaseAccessTokenGrantRequestExtractor {
private static final Logger LOGGER = LoggerFactory.getLogger(AccessTokenAuthorizationCodeGrantRequestExtractor.class);
public AccessTokenAuthorizationCodeGrantRequestExtractor(final ServicesManager servicesManager, final TicketRegistry ticketRegistry,
final HttpServletRequest request, final HttpServletResponse response,
final CentralAuthenticationService centralAuthenticationService,
final OAuthProperties oAuthProperties) {
super(servicesManager, ticketRegistry, request, response, centralAuthenticationService, oAuthProperties);
}
@Override
public AccessTokenRequestDataHolder extract() {
final ProfileManager manager = WebUtils.getPac4jProfileManager(request, response);
final String grantType = request.getParameter(OAuth20Constants.GRANT_TYPE);
LOGGER.debug("OAuth grant type is [{}]", grantType);
final Optional<UserProfile> profile = manager.get(true);
final String clientId = profile.get().getId();
final OAuthRegisteredService registeredService = OAuth20Utils.getRegisteredOAuthService(this.servicesManager, clientId);
LOGGER.debug("Located OAuth registered service [{}]", registeredService);
// we generate a refresh token if requested by the service but not from a refresh token
final boolean generateRefreshToken = isAllowedToGenerateRefreshToken(registeredService);
final OAuthToken token = getOAuthTokenFromRequest();
if (token == null) {
throw new InvalidTicketException(getOAuthParameter());
}
return new AccessTokenRequestDataHolder(token, generateRefreshToken, registeredService);
}
/**
* Is allowed to generate refresh token ?
*
* @param registeredService the registered service
* @return the boolean
*/
protected boolean isAllowedToGenerateRefreshToken(final OAuthRegisteredService registeredService) {
return registeredService != null && registeredService.isGenerateRefreshToken();
}
protected String getOAuthParameterName() {
return OAuth20Constants.CODE;
}
protected String getOAuthParameter() {
return request.getParameter(getOAuthParameterName());
}
/**
* Return the OAuth token.
*
* @return the OAuth token
*/
protected OAuthToken getOAuthTokenFromRequest() {
final OAuthToken token = this.ticketRegistry.getTicket(getOAuthParameter(), OAuthToken.class);
if (token == null || token.isExpired()) {
LOGGER.error("OAuth token indicated by parameter [{}] has expired or not found: [{}]", getOAuthParameter(), token);
if (token != null) {
this.ticketRegistry.deleteTicket(token.getId());
}
return null;
}
return token;
}
/**
* Supports the grant type?
*
* @param context the context
* @return true/false
*/
@Override
public boolean supports(final HttpServletRequest context) {
final String grantType = context.getParameter(OAuth20Constants.GRANT_TYPE);
return OAuth20Utils.isGrantType(grantType, OAuth20GrantTypes.AUTHORIZATION_CODE);
}
}