[security-dev] Credentials API redesign

David M. Lloyd david.lloyd at redhat.com
Thu Dec 6 11:12:12 EST 2012


Comments inline, extra stuff trimmed.

On 12/05/2012 08:18 PM, Shane Bryzak wrote:
> Hey guys,
>
> I've completed the first round of redesigns for the credentials API
> based on the feedback provided by Darran and others.
[...]
> To try and present this in a logical manner, I'm going to describe the
> credentials API in terms of the chronological order of events during the
> authentication process.  To start with, let's take a look at the
> LoginCredentials interface:
>
> public interface LoginCredentials {
>       void invalidate();
> }

General invalidation is a good idea.

> [...]
> Let's take a look at an implementation supporting the most common form
> of credentials, a username and password:
>
> public class UsernamePasswordCredentials implements LoginCredentials {
>
>       private String username;
>
>       private PasswordCredential password;
>
>       public String getUsername() {
>           return username;
>       }
>
>       public void setUsername(String username) {
>           this.username = username;
>       }
>
>       public PasswordCredential getPassword() {
>           return password;
>       }
>
>       public void setPassword(PasswordCredential password) {
>           this.password = password;
>       }
>
>       @Override
>       public void invalidate() {
>           username = null;
>           password.clear();
>       }
> }
>
> This implementation provides the capability for setting a username
> (represented as a String) and a PasswordCredential.  Other
> implementations are free to define whichever properties they require,
> for example a CertificateCredentials class may simply contain an
> X509CertificateCredential and nothing else.

I have concern over PasswordCredential.  There are many ways in which a 
password may be verified.  It may be stored in the clear, or maybe with 
some two-way encryption in the way.  It may be stored as a salt of 
various length plus a hash of various protocol.  It may be stored as a 
pure hash.  Not only is there a wide variation in *how* the password can 
be stored, but that variation can occur within a single identity store 
(e.g. older users may be hashed with a weaker hash as time goes on and 
stronger hash algorithms are introduced, for example the progression 
between UNIX crypt->md5 crypt->sha1 crypt passwords; or a store might 
contain a combination of clear and hashed passwords).

Finally, the way a password is stored directly affects what 
authentication mechanisms it can support.  For example a clear password 
allows for many challenge/response protocols that are not possible with 
salt+hash password.  Some protocols like SASL DIGEST-MD5 can support 
passwords that have been simply hashed in a certain way.

I don't see a LoginCredentials-style interface successfully 
encapsulating this concept.

> Once the user provides their credentials, the LoginCredentials instance
> can be passed to IdentityManager via the following method:
>
> public interface IdentityManager {
>       User validateCredentials(LoginCredentials credentials);
> }

Validation is highly protocol-specific.  There's a basic assumption here 
that the credentials being tested are similar or equivalent in form and 
structure to the credentials being tested against; this is almost never 
true in practice.  For challenge/response authentications, the server 
might never see the client's real credentials; approval is a result of a 
conversational protocol in this case.  Thus the credentials presented by 
the user, the conversation across the wire, and the server's credentials 
might all be different.

I think that the only way to encapsulate this is to allow for 
credentials to be defined by their traits.  For example, we can ask, for 
each credential type:

1) Does it have the ability to validate a char[] password?
2) Does it have the ability to yield a char[] password?
3) Is it a one-way hash?  If so:
3.1) What hash algorithm was used?
3.2) What is the salt, if any?
3.3) What salt algorithm was used?
4) Is there a shared key involved (i.e. a byte[] password)?
4.1) Is the shared key specified by a particular protocol?
5) Is there a private key involved?  If so, what's its algorithm?
...etc...

The answers to these questions are not always mutually exclusive.  But, 
the answers will directly influence what kinds of authentication can 
take place against that particular identity.

Finally there's the notion of federated identity management - what if I 
want to delegate my authentication request to PAM or another external 
API?  How would that look from the perspective of IDM?  Theoretically 
external IDM systems *should* be able abstract themselves using the same 
API.  It just doesn't seem to me that the proposed SPI will be able to 
encapsulate all of this stuff.

-- 
- DML


More information about the security-dev mailing list