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; } }