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 thesystem_auth.rolestable. 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): ExtendsPasswordAuthenticatorto 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).
Option C: mTLS with Password Fallback (Recommended)
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:
- Test password authentication by connecting with
cqlsh -u <username> -p <password>. - 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. - 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.yamlbased on your needs:PasswordAuthenticatorfor passwords only,MutualTlsAuthenticatorfor certificates only, orMutualTlsWithPasswordFallbackAuthenticatorfor both. - Enable client encryption with
require_client_auth: truebefore using any mTLS-based authenticator, as the TLS handshake must complete before certificate validation occurs. - Configure
CassandraRoleManageras 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →