# How to Configure Authentication with PasswordAuthenticator and MutualTlsAuthenticator in Cassandra

> Learn to configure Cassandra authentication using PasswordAuthenticator and MutualTlsAuthenticator. Secure your database with username/password or client certificate validation.

- Repository: [The Apache Software Foundation/cassandra](https://github.com/apache/cassandra)
- Tags: how-to-guide
- Published: 2026-07-29

---

**To configure authentication with PasswordAuthenticator and MutualTlsAuthenticator in Apache Cassandra, set the `authenticator` class in [`cassandra.yaml`](https://github.com/apache/cassandra/blob/main/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`](https://github.com/apache/cassandra/blob/main/conf/cassandra.yaml). According to the source code in [`src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java`](https://github.com/apache/cassandra/blob/main/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.

```yaml
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`](https://github.com/apache/cassandra/blob/main/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:

```yaml
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`](https://github.com/apache/cassandra/blob/main/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:

```yaml
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`](https://github.com/apache/cassandra/blob/main/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:

```yaml
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`](https://github.com/apache/cassandra/blob/main/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`](https://github.com/apache/cassandra/blob/main/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java), lines 55-63).

Configure the role manager in [`cassandra.yaml`](https://github.com/apache/cassandra/blob/main/cassandra.yaml):

```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:

```bash
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:

```java
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:

```java
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:

```sql
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`](https://github.com/apache/cassandra/blob/main/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`](https://github.com/apache/cassandra/blob/main/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`](https://github.com/apache/cassandra/blob/main/cassandra.yaml) has `enabled: true`, `optional: false`, and `require_client_auth: true`. According to the source code in [`MutualTlsAuthenticator.java`](https://github.com/apache/cassandra/blob/main/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.