Authentication
Aeron Cluster supports authenticating Client connections (ClusterSessions). When a client connects, encoded credentials can be passed in the SessionConnectRequest. Those can be authenticated, or followed by a challenge-response exchange.
There is a DefaultAuthenticator that does not authenticate and simply marks ClusterSessions as authenticated. There is also a SampleAuthenticator in Aeron Archive, but you are best to implement your own if you want authentication.
Authenticator¶
Aeron has an Authenticator interface, which is used in Aeron Cluster and Aeron Archive. The comments below describe how it's used in Aeron Cluster.
public interface Authenticator
{
// called when SessionConnectRequest is received, but the Egress is not yet connected
void onConnectRequest(long sessionId, byte[] encodedCredentials, long nowMs);
// called when ChallengeResponse received on the Ingress
void onChallengeResponse(long sessionId, byte[] encodedCredentials, long nowMs);
// called repeatedly from slowTickWork (every 10 ms) after SessionConnectRequest
// and Egress connected, but Challenge has not been sent
void onConnectedSession(SessionProxy sessionProxy, long nowMs);
// called repeatedly from slowTickWork (every 10ms) after SessionConnectRequest
// and Egress connected, and Challenge has been sent
void onChallengedSession(SessionProxy sessionProxy, long nowMs);
}
SessionProxy¶
The SessionProxy interface is implemented by ClusterSessionProxy when used in Aeron Cluster. It's a wrapper around the ClusterSession and EgressPublisher, which can send a Challenge request on the Egress, and mark the ClusterSession as authenticated or rejected.
public interface SessionProxy
{
// Get the session's id
long sessionId();
// Ask the session to send a Challenge to the client
boolean challenge(byte[] encodedChallenge);
// Mark session as authenticated
boolean authenticate(byte[] encodedPrincipal);
// Mark session as rejected
void reject();
}
Workflow¶
In Aeron Cluster, when the ConsensusModuleAgent receives the SessionConnectRequest on the Ingress, it calls
onConnectRequest()
on the Authenticator, passing in the encodedCredentials
. The SessionProxy is not passed in at
this stage (because the Egress is not yet connected), so the session can't be challenged, or marked authenticated /
rejected, but the Authenticator can store the credentials for the session, keyed against the sessionId.
Slow tick work¶
Within slow tick work
(covered later, but it's work that happens in the Consensus
Module every 10 ms), the ConsensusModuleAgent checks whether the ClusterSession has
established its Egress connection.
Once it has, then it calls one of onConnectedSession()
or onChallengedSession()
, depending on the state of the
ClusterSession. To begin with, onConnectedSession()
is called, which is passed a reference to the SessionProxy.
Depending on how you implement the Authenticator, it can choose to authenticate the ClusterSession using the
credentials it stored in onConnectRequest()
, or ask the SessionProxy to challenge the client. If challenged, the
SessionProxy sends a Challenge request on the Egress and moves the ClusterSession into the CHALLENGED
state.
When in the CHALLENGED state, slow tick work
calls onChallengedSession()
. This gives the Authenticator an
opportunity to time out the challenge and reject the ClusterSession, if so desired.
ChallengeResponse¶
If a Challenge was sent on the Egress, the client is expected to respond with a ChallengeResponse on the
Ingress. When this is received, onChallengeResponse()
is called, where the Authenticator can decide whether the
ClusterSession should be authenticated or rejected. However, onChallengeResponse()
isn't given the SessionProxy, so it needs to store decision and wait for the next call to onChallengedSession()
.
onChallengedSession()
can then mark the session as authenticated or rejected, by calling the appropriate method on
the SessionProxy.