Following on, here's an extremely basic example of an Authenticator. If
a developer were to simply include this class in their application and
perform no further configuration, then it would be used during the
authentication process:
public class SimpleAuthenticator extends BaseAuthenticator implements
Authenticator
{
@Inject
Credentials credentials;
public void authenticate()
{
if ("demo".equals(credentials.getUsername()) &&
credentials.getCredential() instanceof
PasswordCredential &&
"demo".equals(((PasswordCredential)
credentials.getCredential()).getValue())) {
setStatus(AuthenticationStatus.SUCCESS);
setUser(new SimpleUser("demo"));
}
else
{
setStatus(AuthenticationStatus.FAILURE);
}
}
}
In this example, BaseAuthenticator is an abstract class that implements
most of the Authenticator methods and simply allows the subclass to
invoke setStatus / setUser / addGroup etc to set the user's
authentication state.
On 29/02/12 08:15, Shane Bryzak wrote:
With the basic implementation of Identity now in place, it's now a
good time to discuss authentication. The authentication API comes
into play during the user authentication process, and is responsible
for ensuring that the user is who they claim to be, and providing the
application with the user's assigned role and group privileges. The
authentication API is not invoked directly by the user, rather it is
consumed by the login process when the user invokes Identity.login().
It should be easily configured and simple to extend.
The following code shows the proposed SPI interface for Authenticator,
an implementation of which manages the authentication process:
public interface Authenticator
{
public enum AuthenticationStatus {SUCCESS, FAILURE, DEFERRED}
void authenticate();
void postAuthenticate();
AuthenticationStatus getStatus();
User getUser();
Set<Role> getRoleMemberships();
Set<Group> getGroupMemberships();
}
The AuthenticationStatus enum / getStatus() method are used to
indicate the current state of authentication. Once the authenticate()
method has been invoked and completed, in most cases the getStatus()
method will return a result of SUCCESS or FAILURE, indicating whether
the authentication process was successful or not. In more complex
forms of Authentication (such as OpenID) the getStatus() method will
return an immediate result of DEFERRED, indicating that the
authentication process is still underway.
The postAuthenticate() method in most cases will do nothing, however
is provided once again for more complex authentication scenarios. It
allows the authenticator to perform finalisation of the authentication
process, for example in cases where authentication is asynchronous.
The last three methods are responsible for providing the user's state
to the Identity bean. The User instance, along with their role and
group privileges will be used to populate Identity for the duration of
the user's session.
I propose that we provide the following Authenticator implementations
out of the box:
1. IdmAuthenticator - Performs user authentication against the
Identity Management API
2. JaasAuthenticator - Allows the user to use an existing JAAS
configuration to authenticate with
3. OpenIdAuthenticator - Performs authentication using an OpenID
provider, such as Google
We can easily extend this list in the future. I furthermore propose
the following logic to select which Authenticator will be used when
invoking Identity.login(), in descending order of priority:
1. If the developer has configured a specific Authenticator
implementation to use by setting Identity.authenticatorClass, then use
that Authenticator.
2. If the user has selected a specific authenticator to use by name,
by setting Identity.authenticatorName, then lookup the Authenticator
with that name and use it. This use case is useful for when you wish
to provide multiple authentication alternatives to the user. For
example, Sourceforge allows a user to either log in using their
Sourceforge username and password, or with their OpenID account.
3. If the developer has provided their own Authenticator
implementation, then use it to authenticate. This is the simplest use
case and allows the developer to control the authentication process
themselves.
4. If the Identity Management API has been configured and identity
management services are available, then use IdmAuthenticator to
authenticate the user against the configured identity store.
This authenticator selection process provides sensible defaults, while
allowing the developer to easily control and/or override the
authenticator configuration.