Apache Geode CHANGELOG

Implementing Authentication

Authentication lends a measure of security to a cluster by verifying the identity of components as they connect to the system. All components use the same authentication mechanism.

How Authentication Works

When a component initiates a connection to the cluster, the SecurityManager.authenticate method is invoked. The component provides its credentials in the form of properties as a parameter to the authenticate method.

The credentials parameter is generated by the security-client-auth-init class’s getCredentials() call, for example a token, a certificate, or a user/password combination. The authenticate method is expected to either return an object representing a principal or throw an AuthenticationFailedException or AuthenticationExpiredException. The principal object is what is passed on to the authorize method which is discussed in detail in the authorization section.

In case of an AuthenticationExpiredException the Geode client code will make one automatic attempt to re-connect to the member that sent the exception. A SecurityManager implementation that supports reauthentication using expiring credentials must also support non-expiring credentials for cluster members.

A well-designed authenticate method will have a set of known credentials, such as user and password pairs, that can be compared to the credentials presented or will have a way of obtaining those credentials.

How a Server Sets Its Credentials

In order to connect with a locator that performs authentication, a server must set its credentials, a username and password specified as the two properties security-username and security-password. In case of systems that use tokens for authentication the property security-token should be provided.

Choose one of two ways to set the server credentials:

  • Add settings to the server properties file, if the credentials comprise a simple username/password combination, or
  • Implement the AuthInitialize interface for the server

Add Settings to the Server Properties File

Set security-username and security-password or security-token in the server’s gfsecurity.properties file, which is read upon server startup. For example:

security-username=admin
security-password=xyz1234

Or:

security-token=abcdxyz

The username, password, and tokens are generally base64 encoded strings which are stored in cleartext, so the gfsecurity.properties file must be protected by restricting access with file system permissions.

Implement the AuthInitialize Interface for the Server

To implement the AuthInitialize interface for the server, set the security-peer-auth-init property so that an object of the class that implements the AuthInitialize interface will be instantiated. There are two ways to do this:

  • You can set the security-peer-auth-init property to the fully-qualified class name that implements the AuthInitialize interface as in the example
  security-peer-auth-init=com.example.security.ServerAuthenticate
  • You can set the security-peer-auth-init property to the fully-qualified method name of a method that instantiates an object of the class that implements the AuthInitialize interface as in the example
  security-peer-auth-init=com.example.security.ServerAuthenticate.create

Implement the getCredentials method within the AuthInitialize interface to acquire values for the security-token property or the security-username and security-password properties in whatever way you wish. For example, it might look up values in a database or another external resource.

Gateway senders and receivers communicate as components of their respective server members. Therefore, the credentials of the server become those of the gateway sender or receiver.

How a Client Cache Sets its Credentials

In order to connect with a locator or a server that performs authentication, a client must set its credentials. The credentials parameter is generated by the security-client-auth-init class’s getCredentials() call, for example a token, a certificate, or a user/password combination.

You must perform two actions to set to set the client credentials:

  • Implement the AuthInitialize interface for the client
  • Provide Authinitialize.getCredentials() with secure access to the client credentials

Implement the AuthInitialize Interface for the Client

To implement the AuthInitialize interface for the client, set the security-client-auth-init property, so that an object of the class that implements the AuthInitialize interface will be instantiated. There are two ways to do this:

  • You can set the security-client-auth-init property to the fully-qualified class name that implements the AuthInitialize interface as in the example:
  security-client-auth-init=com.example.security.ClientAuthInitialize
  • You can set the security-client-auth-init property to the fully-qualified name of a static method that instantiates an object of the class that implements the AuthInitialize interface as in the example
  security-client-auth-init=com.example.security.ClientAuthInitialize.create

Implement the getCredentials() method of the AuthInitialize interface for the client to acquire values for the security-token property or the security-username and security-password properties in whatever way wish. For example, it might look up values in a database or another external resource, or it might prompt for values.

When implementing the getCredentials() method for a token based system keep in mind that the token provider may return an existing token for a user and that this token may expire sooner than expected. Make sure to understand the implications of this and consider building in a check for imminent expiry in the getCredentials() implementation so that a newly fetched but soon to be expired token does not cause undesired exceptions when used for operations.

Provide Secure Access to Client Credentials

Set the security-token property or the security-username and security-password properties for the client in a way that can be accessed by the getCredentials implementation in AuthInitialize. This can be done via the APIs, properties file or other external sources:

Properties properties = new Properties();
properties.setProperty("security-username", "exampleuser23");
properties.setProperty("security-password", "xyz1234");
ClientCache cache = new ClientCacheFactory(properties).create();

For security, take care that credentials set in this manner are not accessible to observers of the code.

How Other Components Set Their Credentials

gfsh prompts for the username and password upon invocation of agfsh connect command. These username/password combinations will be provided as properties to the authenticate method in the keys of security-username and security-password.

Pulse prompts for the username and password upon start up.

Due to the stateless nature of the REST API, a web application or other component that speaks to a server or locator via the REST API goes through authentication on each request. The header of the request needs to include attributes that define values for security-username and security-password or in case of token based security the appropriate header associated with the scheme such as Authorization: Bearer [encoded token-string] for OAuth

Implement SecurityManager Interface

Complete these items to implement authentication done by either a locator or a server.

  • Decide upon an authentication algorithm. The Authentication Example stores a set of username and password pairs that represent the identities of components that will connect to the system. This simplistic algorithm returns the username as a principal if the username and password passed to the authenticate method are a match for one of the stored pairs.
  • Define the security-manager property. See Enable Security with Property Definitions for details about this property.
  • Implement the authenticate method of the SecurityManager interface.
  • Define any extra resources that the implemented authentication algorithm needs in order to make a decision.