/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.authenticator;

import java.io.IOException;
import java.security.Principal;
import java.security.cert.X509Certificate;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.Request;

An Authenticator and Valve implementation of authentication that utilizes SSL certificates to identify client users.
Author:Craig R. McClanahan
/** * An <b>Authenticator</b> and <b>Valve</b> implementation of authentication * that utilizes SSL certificates to identify client users. * * @author Craig R. McClanahan */
public class SSLAuthenticator extends AuthenticatorBase { // --------------------------------------------------------- Public Methods
Authenticate the user by checking for the existence of a certificate chain, validating it against the trust manager for the connector and then validating the user's identity against the configured Realm.
Params:
  • request – Request we are processing
  • response – Response we are creating
Throws:
/** * Authenticate the user by checking for the existence of a certificate * chain, validating it against the trust manager for the connector and then * validating the user's identity against the configured Realm. * * @param request Request we are processing * @param response Response we are creating * * @exception IOException if an input/output error occurs */
@Override protected boolean doAuthenticate(Request request, HttpServletResponse response) throws IOException { // NOTE: We don't try to reauthenticate using any existing SSO session, // because that will only work if the original authentication was // BASIC or FORM, which are less secure than the CLIENT-CERT auth-type // specified for this webapp // // Change to true below to allow previous FORM or BASIC authentications // to authenticate users for this webapp // TODO make this a configurable attribute (in SingleSignOn??) if (checkForCachedAuthentication(request, response, false)) { return true; } // Retrieve the certificate chain for this client if (containerLog.isDebugEnabled()) { containerLog.debug(" Looking up certificates"); } X509Certificate certs[] = getRequestCertificates(request); if ((certs == null) || (certs.length < 1)) { if (containerLog.isDebugEnabled()) { containerLog.debug(" No certificates included with this request"); } response.sendError(HttpServletResponse.SC_UNAUTHORIZED, sm.getString("authenticator.certificates")); return false; } // Authenticate the specified certificate chain Principal principal = context.getRealm().authenticate(certs); if (principal == null) { if (containerLog.isDebugEnabled()) { containerLog.debug(" Realm.authenticate() returned false"); } response.sendError(HttpServletResponse.SC_UNAUTHORIZED, sm.getString("authenticator.unauthorized")); return false; } // Cache the principal (if requested) and record this authentication register(request, response, principal, HttpServletRequest.CLIENT_CERT_AUTH, null, null); return true; } @Override protected String getAuthMethod() { return HttpServletRequest.CLIENT_CERT_AUTH; } }