AuthenticationException Heirarchy

DRAFT DOCUMENT to discuss ideas

One of the goals for Milestone 2 is to achieve a rich AuthenticationException heirarchy.

The root of the heirarchy will be a generic AuthenticationException. AuthenticationExceptions will be checked exceptions (i.e. extending Exception). They will define one extra method:

  • String getCode()

getCode() will include a code to identify the exception. These are designed to be immutable so that any client receiving an exception will be able to recognize it. Our default controllers will be able to map these codes to an external messages.properties file in order to facilitate internationalization.

Tree:

 
+ AuthenticationException  (Abstract.  Declares getCode() method).
|   Authentication failed for some reason, whether that be we were
|    clueless about how to handle the presented credentials, 
|    the presented credentials were bogus,
|    the presented credentials were expired, 
|    whatever.
|
|
|-----+ BasicCredentialsException
|         Basic generic AuthenticationException that is not abstract.
|         Exists to make AuthenticationException itself being abstract pallatable.
|         Strongly encourage using another, more expressive exception rather than this catch-all.
|
|
+-----+ UnsupportedCredentialsException - 
|         the credentials fed to a credentials consumer were not of a type
|         that the consumer knew how to handle.
|
|
+-----+ BadCredentialsException
|     |    The credentials were of a type that could be handled and they didn't 
|     |    successfully authenticate anyone.
|     |      See proposed subclasses for examples.
|     |
|     +------+ BadUsernameOrPasswordException
|            |   The credentials were of a username and password type, probably UsernamePasswordCredentials, 
|            |   and they were bad because the password did not match the username.  The username might be
|            |   inherently bad, such that there exists no password that would have authenticated for this
|            |   username.  Or the username might be just fine.  Throwers will choose to throw this Exception
|            |   rather than either of its subclasses because they either 1) don't want to expose whether
|            |   the username was a valid username, or 2) are unable to expose that information because
|            |   actual username/password checking is happening across an abstraction boundary that doesn't
|            |   differentiate.
|            |
|            |
|            +-------+ UnknownUsernameException
|            |          The credentials were bad because the purported username was not recognized. There exists
|            |          no password that would have worked for this username.  
|            |          (Implied hint to the UI layer: the user may have mistyped his username.)
|            |
|            |
|            +-------+ BadPasswordException
|            |          The credentials were bad because the password was not valid for the given username.
|            |          However, the username itself was a valid username.  There exists some password that will
|            |          work for this username. 
|            |          (Implied hint to the UI layer: the user may have mistyped his password.)
|            |
|            |
|            |-------+ InvalidCertificateException
|                      The credentials were bad because the Certificate provided 
|                      does not match what we were expecting
|                      that principal to provide.
| 
|
|-----+ BlockedCredentialsException
|     |  The credentials would have been valid if not for some problem about them.
|     |
|     +------+ CertificateExpiredException
|     |           The credentials were a certificate and the cert was expired and so invalid.
|     |           Had it not been expired, it would have been valid.
|     |
|     |
|     +------+ AccountLockedException
|     |           The user is administratively blocked from authenticating despite having presented
|                 Otherwise valid credentials.
|
|
|-----+ AuthHandlerFailure
|         An AuthHandler would throw this exception when it is unable to perform its function 
|         due to internal or external problems (database or network down, program failure). 
|         AuthenticationManagers also generate and log this exception
|         when an AuthenticationHandler is has called throws any exception that does not extend
|         AuthenticationException (e.g. NullPointerException).
|         Generally there will be a Throwable chained to instances of AuthHandlerFailures
|         communicating the underlying cause of the failure.
|          This exception is analogous to the DataAccessResourceFailureException of the Spring 
|          DataAccessException hierarchy.
|
| 
|-----+ AccessProhibited
|         An AuthHandler would throw this exception when it has reason to believe that 
|         the authenticating user should not be allowed to authenticate regardless of his or her
|         having been authenticated by other AuthenticationHandlers. 
|         The motivation is that the handler throwing this exception knows this is an employee 
|         terminated or student expelled last week who may have a grudge and should be 
|         blocked from authenticating. Not all systems may have been updated, so this exception 
|         allows a system with more recent information to veto logon even if the user was 
|         authenticated by a previous AuthHandler.