| --- | |
| title: Implementing Authentication | |
| sidebar_label: Implementing Authentication | |
| sidebar_position: 1 | |
| --- | |
| <!-- | |
| 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. | |
| ## How Authentication Works {#authentication-how-it-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) section. | |
| In case of an `AuthenticationExpiredException` the @@product_name@@ client code will make one automatic attempt | |
| to re-connect to the member that sent the exception. | |
| 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 {#authentication-server-set-creds} | |
| 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 {#authentication-setserverprops} | |
| 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. | |
| ### Implement the AuthInitialize Interface for the Server {#authentication-implementserverinterface} | |
| 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. | |
| ## How a Client Cache Sets its Credentials {#authentication-client-set-creds} | |
| 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 {#authentication-implementclientinterface} | |
| 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. | |
| ### Provide Secure Access to Client Credentials {#authentication-provideclientcredaccess} | |
| 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. | |
| ## How Other Components Set Their Credentials {#authentication-component-set-creds} | |
| `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` | |
| ## Implement SecurityManager Interface {#authentication-implement-security-mgr} | |
| Complete these items to implement authentication done by either a | |
| locator or a server. | |
| - Decide upon an authentication algorithm. | |
| The [Authentication Example](authentication_examples) | |
| 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) | |
| 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. |