I can see that there are cases where we know the User so it is desirable
to supply it but there are still the cases where we don't know the user
until after the credential has been verified.
Regards,
Darran Lofthouse.
On 12/06/2012 02:51 PM, Bill Burke wrote:
On 12/6/2012 8:32 AM, Darran Lofthouse wrote:
>> The main idea is decouple from the IDM the logic to store, load and
validate credentials. That should be done by some client API like PicketLink Core,
PicketBox or some other authentication API. The IDM can provide some built-in
implementations for PasswordCredentialHandler or X509CertificateCredentialHandler, for
example.
>>
>> Another possible benefit is that the IDM does not need to know about how
credentials/handlers are configured.
>>
>> The handler can just use the IdentityManager to store the credentials,
using user's attributes or something like that.
>>
>> Let's say we want to perform a username/password authentication:
>>
>> Client Code
>>
>> UsernamePasswordCredential credential = new
UsernamePasswordCredential("username","passwd");
>> PasswordCredentialHandler credentialHandler = new
PasswordCredentialHandler(credential);
>>
>> if (identityManager.validateCredential(credentialHandler)) {
>> User user = identityManager.getUser(credential.getUsername);
>>
>> // continue with the authentication
>> } else {
>> // handle bad user
>> }
>>
>> Now, let's say we want some some authentication that requires several
steps (otp authentication using username + password + token):
>>
>> OTPCredential credential = new OTPCredential("username",
"passwd"); // the user can also provide the token. no challenge.
>> OTPCredentialHandler credentialHandler = new
OTPCredentialHandler(credential);
>>
>> if (identityManager.validateCredential(credentialHandler)) {
>> // valid user, token was already provided by the user
>> } else if
(credentialHandler.getStatus().equals(OTPCredentialHandler.TOKEN_CHALLENGE)) {
>> // tell the user that we also need the token to perform the
authenticatin
>> } else {
>> // handle bad user
>> }
>>
>> Makes sense ?
>
> I like this, for the scenarios I have mentioned where additional
> processing is required beyond just authentication the supplied
> CredentialHandler can now be involved.
>
> CredentialHandlers will require access to sensitive attributes of a user
> but we also have the ability here to detect that it is within the
> "identityManager.validateCredential" call to only allow at that point.
>
First off, I think User should be a parameter to your validate() method.
Second, I think this idea was floated around previously (months ago). I
liked the idea of a typed interface for credential handling, and the
separaation of concerns, but now that I'm actually prototyping an
REST-based IDP, I'm having second thoughts about a typed interface. In
my prototype, the IDP may dynanmically generate a login.html form based
on the credential types required by the realm. It doesn't know whether
or not the credential type is a password, OTP, mother's maiden name, or
whatever, it just needs to know to ask the user for a bunch of inputs.
Same thing goes with validation. Client-cert only validation adds an
addtional complication as the IDP wouldn't even need to display a login
form.
I think it should be something more like this:
public interface CredentialType implements Serializable {
CredentialHandler getHandler(User user, IdentityManager manager);
}
public interface CredentialHandler {
boolean validate(User user, Object[] credentials, IdentityManager idm);
}
public interface IdentityManager {
CredentialType[] getCredentialTypes(User user);
}
The above gives the consumer of this IdentityManager API a lot of
flexibility. The IDM API library would still provide a core set of
CredentialHandler implementations and a default implementations for
various CredentialTypes, but a consumer could easily provide extensions
that stored additional metadata. For example
public interface FormCredentialType {
String getDescription(Locale locale);
String getFormInputLable(Locale locale);
String getFormInputVariableName();
String getFormInputType();
String getFormInputSize();
}
public class PasswordFormCredential extends PasswordCredentialType
implements FormCredentialType {
...implmentation of FormCredentialType
}