package org.apereo.cas.digest.web.flow;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy;
import org.apereo.cas.digest.DigestCredential;
import org.apereo.cas.digest.DigestHashedCredentialRetriever;
import org.apereo.cas.digest.util.DigestAuthenticationUtils;
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.pac4j.core.context.HttpConstants;
import org.pac4j.core.context.WebContext;
import org.pac4j.http.credentials.DigestCredentials;
import org.pac4j.http.credentials.extractor.DigestAuthExtractor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.webflow.execution.RequestContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* This is {@link DigestAuthenticationAction} that extracts digest authN credentials from the request.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
public class DigestAuthenticationAction extends AbstractNonInteractiveCredentialsAction {
private static final Logger LOGGER = LoggerFactory.getLogger(DigestAuthenticationAction.class);
private String nonce = DigestAuthenticationUtils.createNonce();
private final DigestHashedCredentialRetriever credentialRetriever;
private String realm = "CAS";
private String authenticationMethod = "auth";
public DigestAuthenticationAction(final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver,
final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver,
final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy,
final String realm,
final String authenticationMethod,
final DigestHashedCredentialRetriever credentialRetriever) {
super(initialAuthenticationAttemptWebflowEventResolver, serviceTicketRequestWebflowEventResolver, adaptiveAuthenticationPolicy);
this.realm = realm;
this.authenticationMethod = authenticationMethod;
this.credentialRetriever = credentialRetriever;
}
@Override
protected Credential constructCredentialsFromRequest(final RequestContext requestContext) {
try {
final HttpServletRequest request = WebUtils.getHttpServletRequest(requestContext);
final HttpServletResponse response = WebUtils.getHttpServletResponse(requestContext);
final DigestAuthExtractor extractor = new DigestAuthExtractor(this.getClass().getSimpleName());
final WebContext webContext = WebUtils.getPac4jJ2EContext(request, response);
final DigestCredentials credentials = extractor.extract(webContext);
if (credentials == null) {
response.addHeader(HttpConstants.AUTHENTICATE_HEADER,
DigestAuthenticationUtils.createAuthenticateHeader(this.realm, this.authenticationMethod, this.nonce));
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return null;
}
LOGGER.debug("Received digest authentication request from credentials [{}] ", credentials);
final String serverResponse = credentials.calculateServerDigest(true,
this.credentialRetriever.findCredential(credentials.getUsername(), this.realm));
final String clientResponse = credentials.getToken();
if (!serverResponse.equals(clientResponse)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return null;
}
return new DigestCredential(credentials.getUsername(), this.realm, credentials.getToken());
} catch (final Exception e) {
LOGGER.error(e.getMessage(), e);
}
return null;
}
}