Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Cassandra Authentication Architecture

Authentication in Cassandra verifies client identity before allowing connections. The protocol uses SASL (Simple Authentication and Security Layer) to provide a consistent handshake flow for the built-in PasswordAuthenticator.

Cassandra implements authentication through SASL, a framework that separates authentication mechanisms from the application protocol:

SASL authentication handshake between client, driver, and CassandraClientDriverCassandraAuthenticatorClientClientDriverDriverCassandraCassandraAuthenticatorAuthenticatorconnect(credentials)STARTUPgetInitialChallenge()challengeAUTHENTICATE(authenticator)create SASL clientAUTH_RESPONSE(response)evaluateResponse(response)successAUTH_SUCCESSconnected
ComponentRoleLocation
AuthenticatorServer-side credential validationCassandra node
AuthProviderClient-side credential supplyDriver
SASL MechanismChallenge-response protocolBoth sides

When authentication is enabled, the server responds to STARTUP with AUTHENTICATE instead of READY:

Client → Server: STARTUP {CQL_VERSION: "3.0.0"}
Server → Client: AUTHENTICATE {authenticator: "org.apache.cassandra.auth.PasswordAuthenticator"}

The authenticator class name indicates which authentication mechanism the server expects.

For PasswordAuthenticator, authentication completes in a single round:

Client → Server: AUTH_RESPONSE {credentials}
Server → Client: AUTH_SUCCESS

AUTH_RESPONSE:

AUTH_RESPONSE {
<token>: [bytes] SASL response token
}

AUTH_CHALLENGE:

AUTH_CHALLENGE {
<token>: [bytes] SASL challenge token
}

AUTH_SUCCESS:

AUTH_SUCCESS {
<token>: [bytes] Optional final token
}

The default and primary authenticator uses username/password credentials stored in Cassandra.

PasswordAuthenticator uses the PLAIN SASL mechanism.

Token = NUL + username + NUL + password
= \x00 + "username" + \x00 + "password"

The token is a byte sequence containing:

  1. A null byte (0x00)
  2. UTF-8 encoded username
  3. A null byte (0x00)
  4. UTF-8 encoded password
PasswordAuthenticator handshake using the PLAIN mechanismClientServerClientClientServerServerSTARTUPAUTHENTICATE [PasswordAuthenticator]AUTH_RESPONSE [\0 user \0 pass]AUTH_SUCCESS

Credentials are stored in the system_auth keyspace:

-- Credentials stored in system_auth.roles
SELECT role, salted_hash FROM system_auth.roles WHERE role = 'username';

Passwords are hashed using bcrypt with a configurable work factor.

Cassandra creates a default superuser on first startup:

UsernameDefault PasswordNotes
cassandracassandraMust be changed in production

Change Default Credentials

The default cassandra/cassandra superuser credentials must be changed immediately in any non-development environment. Leaving default credentials is a critical security vulnerability.


Drivers support multiple credential sources:

SourceUse CaseSecurity
HardcodedDevelopment onlyPoor
Environment variablesContainer deploymentsModerate
Configuration fileTraditional deploymentsModerate
Credential providerProductionGood
Vault integrationEnterpriseBest

Drivers typically provide a credential abstraction:

// Conceptual interface
interface AuthProvider {
// Called when authentication is required
Authenticator newAuthenticator(
InetSocketAddress host,
String authenticator
);
}
interface Authenticator {
// Initial response token
byte[] initialResponse();
// Evaluate server challenge
byte[] evaluateChallenge(byte[] challenge);
// Called on success
void onSuccess(byte[] token);
}

Drivers cache successful authentication:

Cache key: (host, authenticator_class)
Cache value: authenticated_connection
TTL: Connection lifetime
Benefits:
- Avoid repeated authentication
- Reduce load on auth backend
- Faster connection reuse

Cassandra's authenticator plugin interface:

// Simplified interface
public interface IAuthenticator {
// Whether authentication is required
boolean requireAuthentication();
// Supported SASL mechanisms
Set<String> supportedMechanisms();
// Create SASL negotiator for connection
SaslNegotiator newSaslNegotiator(InetAddress clientAddress);
// Validate credentials (legacy)
AuthenticatedUser authenticate(Map<String, String> credentials);
}
AuthenticatorDescription
AllowAllAuthenticatorNo authentication (default)
PasswordAuthenticatorUsername/password authentication

After SASL completes, the server validates the authenticated identity:

1. SASL authentication succeeds
2. Extract username from credentials
3. Lookup role in system_auth.roles
4. Verify role can login (LOGIN = true)
5. Establish session with role identity

Server caches authentication results:

cassandra.yaml
credentials_validity_in_ms: 2000
credentials_update_interval_in_ms: 2000
credentials_cache_max_entries: 1000
ParameterDescription
validityHow long cached credentials are valid
update_intervalBackground refresh interval
max_entriesMaximum cached credentials

Storage:

  • Passwords never stored in plaintext
  • Bcrypt hashing with configurable rounds
  • Salt per password

Transmission:

  • PLAIN mechanism sends password in cleartext within the protocol
  • TLS encryption strongly recommended
  • Without TLS, credentials are visible to network observers

Enable TLS

Without TLS encryption, credentials are transmitted in cleartext and can be captured by network observers. Always enable client-to-node encryption in production environments.

cassandra.yaml
authenticator: PasswordAuthenticator

After enabling, restart all nodes and update client configurations.

Rotating Passwords:

-- 1. Create new role with same permissions
CREATE ROLE new_app_user WITH PASSWORD = 'new_password' AND LOGIN = true;
GRANT existing_role TO new_app_user;
-- 2. Update applications to use new credentials
-- 3. Revoke old credentials
ALTER ROLE old_app_user WITH LOGIN = false;
EventServer ActionClient Action
Wrong passwordERROR (Bad credentials)Report to application
Unknown userERROR (Bad credentials)Report to application
Locked accountERROR (Bad credentials)Report to application

Security Note: Error messages are intentionally vague to prevent user enumeration.

Cassandra has limited built-in protection:

  • No automatic lockout
  • No rate limiting
  • Relies on network-level controls

Recommendations:

  • Use strong passwords
  • Enable TLS
  • Network-level rate limiting
  • Monitor authentication failures
  • Restrict network access to trusted clients

Client connection state machine during authenticationClient connection state machine during authenticationCONNECTINGWAITING_AUTHAUTHENTICATINGREADYFAILEDSTARTUP sentAUTHENTICATE receivedREADY received(no auth)AUTH_SUCCESS receivedERROR received
TimeoutScopeTypical Value
Connection timeoutTCP connect5 seconds
Authentication timeoutSASL exchange12 seconds
Initial handshakeSTARTUP to READY30 seconds

Cassandra nodes also authenticate with each other:

cassandra.yaml
internode_authenticator: org.apache.cassandra.auth.AllowAllInternodeAuthenticator

Options:

  • AllowAllInternodeAuthenticator - No authentication (default)
  • Custom implementations for specific requirements

With internode encryption, certificate validation provides authentication:

server_encryption_options:
internode_encryption: all
require_client_auth: true
truststore: /path/to/truststore.jks

This approach uses mutual TLS (mTLS) where both nodes present certificates that are validated against a trusted certificate authority.


ScenarioTypical LatencyNotes
Cached credentials<1 msCache hit on server
Uncached credentials1-5 msBcrypt verification
  1. Credential caching - Server caches validated credentials
  2. Connection pooling - Amortize authentication cost across requests
  3. Keep-alive - Maintain connections to avoid re-authentication