AMPS and the AMPS clients provide a flexible authentication infrastructure that's designed to get out of your way as much as possible and let you reuse the components you already have. Regardless of how simple or sophisticated your enterprise authentication system is, the AMPS clients make it easy to use that system with AMPS.
In this FAQ, we'll discuss the simple approach that many applications use with AMPS, and the interface that the AMPS client libraries provide for working with more sophisticated systems.
For many applications, providing credentials to AMPS is as simple as including them in the connection string provided to the client. For example, to provide the authentication token 7FFE900-17EF345 for the user DemoMan, you could simply provide those credentials in the connection string as shown below:
These credentials are part of the connection string. For example, a Python application might connect as follows, assuming that your site provides a CredentialManager module for applications to use with your enterprise authentication system. Notice that the only difference between this code and the equivalent unauthenticated code is that the application includes credentials in the connection string.
import CredentialManager # site-specific library
# use the site-specific credential manager to get
# appropriate credentials for the connection
def getConnection(): return "tcp://%s:%s@amps-server:9007/amps/json" % \
# Connect using AMPS Client
client = AMPS.Client("Sample")
# Connect using AMPS HAClient
haclient = AMPS.HAClient("HASample")
sc = AMPS.DefaultServerChooser() # use default for demo purposes
# Add the connection string to the HAClient
Use this method when the authentication token is consistent for multiple logins and the authentication scheme does not require more complicated behavior (such as challenge/response).
Custom Authentication Schemes
AMPS provides a simple interface, called an Authenticator, for managing more sophisticated authentication schemes (for example, systems that require single-use tokens or require challenge-response authentication).
Each time the client makes a connection, an Authenticator returns a token for the connection. Each time the client receives a challenge from the server, an Authenticator generates a response to the challenge.
The interface is intentionally simple. It is designed to be a very lightweight adapter for existing library code. The AMPS Client itself has no special requirements for an Authenticator implementation or for the format or semantics of the authentication tokens.
The interface for the AMPS Authenticator includes three methods:
- authenticate – This method receives the username and token provided in the connection string and returns a token to use to authenticate to the server. Called whenever a new connection is attempted before the AMPS client begins the logon process.
- retry – This method is provided for use with challenge/response authentication systems. The method receives the username and challenge returned by the server and returns the response to the challenge. Called whenever the server returns a retry, as many times as the server responds with a retry. This method can simply return the input token if the server does not issue challenges.
- completed – This method is called with the username, token, and result returned by the server at the end of the logon sequence. Called at the end of each logon sequence. This method can be empty if there is no cleanup or logging required at the end of a logon sequence.
The three methods above are the complete interface for an Authenticator. You provide the Authenticator to the client (or HAClient) as a part of the logon sequence. For the client, it’s just an argument to logon. For the HAClient, the authenticator is managed by the ServerChooser – the ServerChooser manages the Authenticator for a given connection so that it’s easy to provide the correct token each time AMPS connects to a new server, and to allow a client to fail over to a different servers that have a different authentication requirements (or use different certificates, etc.).
For example, the class below is a complete Authenticator in Python. This Authenticator simply provides a token generated from an underlying library.
import TokenGenerator # site-specific library
class SimpleAuthenticator(object): def __init__(self): pass # return token generated according to site policies def authenticate(self, username, token): return TokenGenerator.get_single_use(username) def completed(self,username,password,reason): print "Completed: %s (%s) %s" % (username,password,reason)
# assume server does not use challenge / response def retry(self, username, token): return token
Authenticators have the same methods and are used the same way in Python, Java, C#, and C++ (though there are minor differences in how an Authenticator is implemented in each language).
This simple interface has been successfully used for systems that range in sophistication from simple user/password authentication to Kerberos authentication to custom systems that include permissions assertions and tokens for external systems in the information exchanged between the application and the AMPS server.
As shown above, the AMPS approach to providing credentials is designed for ease of implementation and flexibilty. Rather than introducing new components into your enterprise authentication fabric, the clients are designed to easily work with the infrastructure you already have.
Keywords: authenticator, logon token, password, authentication, credentials, challenge-response authentication