How to Configure Authentication with PasswordAuthenticator and MutualTlsAuthenticator in Cassandra

To configure authentication with PasswordAuthenticator and MutualTlsAuthenticator in Apache Cassandra, set the authenticator class in cassandra.yaml to PasswordAuthenticator for username/password login, MutualTlsAuthenticator for client certificate validation, or MutualTlsWithPasswordFallbackAuthenticator to support both mechanisms simultaneously.

Apache Cassandra provides pluggable authentication mechanisms that allow you to secure your cluster using traditional passwords, mutual TLS (mTLS) client certificates, or a combination of both. This guide explains how to configure authentication with PasswordAuthenticator and MutualTlsAuthenticator based on the source code implementation in the apache/cassandra repository.

Understanding the Three Authentication Modes

Cassandra supports three distinct authentication patterns through different authenticator classes. Each class implements the IAuthenticator interface but handles credentials differently:

  • PasswordAuthenticator (org.apache.cassandra.auth.PasswordAuthenticator): Authenticates users against bcrypt-hashed passwords stored in the system_auth.roles table. This is the traditional username/password approach.
  • MutualTlsAuthenticator (org.apache.cassandra.auth.MutualTlsAuthenticator): Validates client identity using X.509 certificates presented during the TLS handshake. No passwords are exchanged.
  • MutualTlsWithPasswordFallbackAuthenticator (org.apache.cassandra.auth.MutualTlsWithPasswordFallbackAuthenticator): Extends PasswordAuthenticator to first attempt mTLS authentication, then fall back to password validation if the client presents no certificate. This is the recommended approach when you need to support both authentication methods in a single cluster.

Step 1: Enable Client Encryption for mTLS

Before configuring MutualTlsAuthenticator or the fallback variant, you must enable encrypted client connections and require client certificate authentication in conf/cassandra.yaml. According to the source code in src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java (lines 35-38), the authenticator validates certificates only after a successful TLS handshake, making this configuration mandatory.

client_encryption_options:
    enabled: true
    optional: false                # Must be false for mTLS

    require_client_auth: true      # Required for client certificate validation

    keystore: conf/.keystore       # Server certificate and private key

    keystore_password: ********
    truststore: conf/.truststore   # Trusted Certificate Authorities for client certs

    truststore_password: ********

The optional: false setting ensures Cassandra rejects unencrypted connections, while require_client_auth: true mandates that clients present a certificate during the TLS handshake.

Step 2: Configure the Authenticator Class

Edit conf/cassandra.yaml to specify your desired authentication mechanism in the authenticator section. Choose one of the following configurations based on your security requirements.

Option A: Password-Only Authentication

Use this configuration for traditional username/password authentication without certificate requirements:

authenticator:
  class_name: org.apache.cassandra.auth.PasswordAuthenticator

When using PasswordAuthenticator, the system stores credentials as bcrypt hashes in system_auth.roles, which the authenticator reads via its bulkLoader() method (see src/java/org/apache/cassandra/auth/PasswordAuthenticator.java, lines 31-45).

Option B: Mutual TLS Authentication

Use this configuration to require client certificates for all connections:

authenticator:
  class_name: org.apache.cassandra.auth.MutualTlsAuthenticator
  parameters:
    validator_class_name: org.apache.cassandra.auth.SpiffeCertificateValidator

The validator_class_name parameter specifies an implementation of MutualTlsCertificateValidator that extracts and validates the identity from the client certificate. The MutualTlsAuthenticator validates this configuration at startup and logs errors if parameters are missing (see src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java, lines 96-101).

Use this configuration to support both authentication methods, allowing mTLS-aware clients to connect via certificate while legacy clients use passwords:

authenticator:
  class_name: org.apache.cassandra.auth.MutualTlsWithPasswordFallbackAuthenticator
  parameters:
    validator_class_name: org.apache.cassandra.auth.SpiffeCertificateValidator

This authenticator extends PasswordAuthenticator and inherits its constants for username and password handling (USERNAME_KEY and PASSWORD_KEY defined at lines 75-76 of src/java/org/apache/cassandra/auth/PasswordAuthenticator.java). When a client connects, the authenticator first attempts to validate the presented certificate; if no certificate is available, it falls back to the standard password flow.

Step 3: Configure the Role Manager

Both PasswordAuthenticator and MutualTlsWithPasswordFallbackAuthenticator require CassandraRoleManager to store and retrieve role information. The PasswordAuthenticator Javadoc explicitly requires a role manager implementation (see src/java/org/apache/cassandra/auth/PasswordAuthenticator.java, lines 55-63).

Configure the role manager in cassandra.yaml:

role_manager:
  class_name: org.apache.cassandra.auth.CassandraRoleManager

After editing the configuration files, restart each Cassandra node to apply the changes.

Client Connection Examples

Authenticating with cqlsh Using Passwords

When using PasswordAuthenticator or the fallback authenticator, connect using standard username and password credentials:

cqlsh -u alice -p secret123

The cqlsh client sends a credential map containing username and password keys that match the constants defined in PasswordAuthenticator (lines 75-76).

Authenticating with Java Driver Using mTLS

For certificate-based authentication using the DataStax Java driver, configure the SSL context with client certificates but omit explicit credentials:

SSLContext sslContext = SSLContextBuilder
    .withTrustStore("/path/to/truststore", "truststorePwd")
    .withKeyStore("/path/to/keystore", "keystorePwd")
    .build();

Cluster cluster = Cluster.builder()
    .addContactPoint("cassandra.example.com")
    .withSSL(sslContext)  // mTLS authentication
    .build();

When using the fallback authenticator with a client that supports both methods, you can provide both the SSL context and credentials:

Cluster cluster = Cluster.builder()
    .addContactPoint("cassandra.example.com")
    .withSSL(sslContext)               // Attempt mTLS first
    .withCredentials("bob", "bobPwd")  // Fallback password
    .build();

Creating Roles with Passwords

Regardless of which authenticator you choose (provided it supports passwords), create roles using standard CQL:

CREATE ROLE alice WITH PASSWORD = 'alicePwd' AND LOGIN = true;

Troubleshooting and Verification

To verify your authentication configuration:

  1. Test password authentication by connecting with cqlsh -u <username> -p <password>.
  2. Test mTLS authentication by connecting with a Java client configured with a valid client certificate that maps to an authorized identity in system_auth.roles.
  3. Test fallback behavior by connecting with the fallback authenticator configured, first with a client certificate, then without (using only passwords).

If authentication fails, inspect /var/log/cassandra/system.log. The MutualTlsAuthenticator logs configuration errors at startup, such as missing validator_class_name parameters (lines 96-101), while PasswordAuthenticator logs authentication failures during the credential validation phase.

Summary

  • Choose the authenticator class in cassandra.yaml based on your needs: PasswordAuthenticator for passwords only, MutualTlsAuthenticator for certificates only, or MutualTlsWithPasswordFallbackAuthenticator for both.
  • Enable client encryption with require_client_auth: true before using any mTLS-based authenticator, as the TLS handshake must complete before certificate validation occurs.
  • Configure CassandraRoleManager as the role manager when using password-based authentication or the fallback authenticator.
  • Reference the source code in src/java/org/apache/cassandra/auth/ to understand the exact implementation details, including constant definitions and validation logic.

Frequently Asked Questions

Can I use PasswordAuthenticator and MutualTlsAuthenticator simultaneously?

No, you cannot declare both classes simultaneously in cassandra.yaml. To support both authentication methods in the same cluster, use MutualTlsWithPasswordFallbackAuthenticator, which extends PasswordAuthenticator and adds mTLS capability with automatic fallback to password validation when certificates are absent.

What certificate validator should I use with MutualTlsAuthenticator?

You must specify a validator_class_name parameter pointing to an implementation of MutualTlsCertificateValidator, such as org.apache.cassandra.auth.SpiffeCertificateValidator. This validator extracts the identity from the client certificate and verifies it against the authorized identities cache. The MutualTlsAuthenticator validates this configuration at startup and refuses to initialize if the validator class is missing or invalid.

Why does mTLS authentication fail even with valid certificates?

Ensure that client_encryption_options in cassandra.yaml has enabled: true, optional: false, and require_client_auth: true. According to the source code in MutualTlsAuthenticator.java (lines 35-38), the authenticator only validates certificates after the TLS handshake completes. If client encryption is disabled or optional, the necessary certificate chain never reaches the authenticator. Additionally, verify that the certificate identity exists in system_auth.roles.

Is client encryption optional when using MutualTlsAuthenticator?

No, client encryption is mandatory. The MutualTlsAuthenticator relies on the TLS layer to negotiate and present client certificates during the handshake. Without client_encryption_options properly configured, the authenticator cannot access certificate data to validate identities, causing all authentication attempts to fail.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →