class DatawaveAuthenticationMechanism implements AuthenticationMechanism {

    @Override
    public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
        // Pull proxied entity info from the headers. If proxied entities are there, but proxied issuers are missing, then fail authentication immediately.
        String proxiedEntities;
        String proxiedIssuers;
        try {
            proxiedEntities = getSingleHeader(exchange.getRequestHeaders(), PROXIED_ENTITIES_HEADER);
            proxiedIssuers = getSingleHeader(exchange.getRequestHeaders(), PROXIED_ISSUERS_HEADER);
            logger.trace("Authenticating with proxiedEntities={} and proxiedIssuers={}", proxiedEntities, proxiedIssuers);
            if (proxiedEntities != null && proxiedIssuers == null) {
                return notAuthenticated(exchange, securityContext, PROXIED_ENTITIES_HEADER + " supplied, but missing " + PROXIED_ISSUERS_HEADER
                                + " is missing!");
            }
        } catch (MultipleHeaderException e) {
            return notAuthenticated(exchange, securityContext, e.getMessage());
        }
        
        // Pull subject/issuer DN from the SSL client certificate if it's there.
        DatawaveCredential credential = null;
        SSLSessionInfo sslSession = exchange.getConnection().getSslSessionInfo();
        if (sslSession != null) {
            try {
                Certificate[] clientCerts = getPeerCertificates(exchange, sslSession, securityContext);
                if (clientCerts[0] instanceof X509Certificate) {
                    X509Certificate certificate = (X509Certificate) clientCerts[0];
                    credential = new DatawaveCredential(certificate, proxiedEntities, proxiedIssuers);
                }
            } catch (SSLPeerUnverifiedException e) {
                // No action - this mechanism can not attempt authentication without peer certificates, so allow it to drop out to NOT_ATTEMPTED
            }
        }
        // If we're using JWT authentication, then trust the JWT in the header.
        if (jwtHeaderAuthentication) {
            try {
                String authorizationHeader = getSingleHeader(exchange.getRequestHeaders(), "Authorization");
                if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                    credential = new DatawaveCredential(authorizationHeader.substring(7));
                }
            } catch (MultipleHeaderException e) {
                return notAuthenticated(exchange, securityContext, e.getMessage());
            }
        }
        // If we're either not using SSL and/or didn't get user info from the SSL session, then get it from the trusted headers, if we're configured to do so.
        if (credential == null && trustedHeaderAuthentication) {
            try {
                String subjectDN = getSingleHeader(exchange.getRequestHeaders(), SUBJECT_DN_HEADER);
                String issuerDN = getSingleHeader(exchange.getRequestHeaders(), ISSUER_DN_HEADER);
                logger.trace("Authenticating with trusted subject header={} and trusted issuer header={}", subjectDN, issuerDN);
                // If no DN headers supplied, then report that we did not authenticate
                if (subjectDN == null && issuerDN == null) {
                    return notAttempted(exchange);
                }
                // If one of subject or issuer is missing, then report authentication failure.
                if (subjectDN == null || issuerDN == null) {
                    return notAuthenticated(exchange, securityContext, "Missing trusted subject DN (" + subjectDN + ") or issuer DN (" + issuerDN
                                    + ") for trusted header authentication.");
                }
                credential = new DatawaveCredential(subjectDN, issuerDN, proxiedEntities, proxiedIssuers);
            } catch (MultipleHeaderException e) {
                return notAuthenticated(exchange, securityContext, e.getMessage());
            }
        }
        
        logger.trace("Computed credential = {}", credential);
        if (credential != null) {
            String username = credential.getUserName();
            
            IdentityManager idm = getIdentityManager(securityContext);
            Account account = idm.verify(username, credential);
            if (account != null) {
                return authenticated(exchange, securityContext, account);
            }
        }
        
        return notAttempted(exchange);
    }

    @SuppressWarnings("UnusedDeclaration") public  DatawaveAuthenticationMechanism();
    @SuppressWarnings("UnusedDeclaration") public  DatawaveAuthenticationMechanism(String mechanismName);
    @SuppressWarnings("UnusedDeclaration") public  DatawaveAuthenticationMechanism(boolean forceRenegotiation);
    public  DatawaveAuthenticationMechanism(String mechanismName, boolean forceRenegotiation, IdentityManager identityManager);

}