blob: 972ed9d57a1c8c9be610b510921550347bab1d9a [file] [log] [blame]
---
title: Implementing Authentication
---
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
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.
## <a id="authentication-how-it-works"></a>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](authorization_overview.html) section.
In case of an `AuthenticationExpiredException` the <%=vars.product_name%> 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.
## <a id="authentication-server-set-creds"></a>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
### <a id="authentication-setserverprops"></a>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:
``` pre
security-username=admin
security-password=xyz1234
```
Or:
```pre
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.
### <a id="authentication-implementserverinterface"></a>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
``` pre
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
``` pre
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.
## <a id="authentication-client-set-creds"></a>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
### <a id="authentication-implementclientinterface"></a>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:
``` pre
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
``` pre
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.
### <a id="authentication-provideclientcredaccess"></a>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:
``` pre
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.
## <a id="authentication-component-set-creds"></a>How Other Components Set Their Credentials
`gfsh` prompts for the username and password upon invocation of
a`gfsh 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`
## <a id="authentication-implement-security-mgr"></a>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](authentication_examples.html)
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](enable_security.html)
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.