What is a semantically correct superclass for an exception thrown in case of an unsupported authentication scheme?

Imagine a server (for example, a Gateway) receives a request that contains an Authorization header with an unsupported authentication scheme (for example, “phony-scheme 12134567890”). I created UnsupportedAuthenticationSchemeException which is thrown in such cases. What should it extend? My short list:

1. org.springframework.security.core.AuthenticationException

Pros:

  • Existing clients may already catch it, no additional catch branches are required

Cons:

  • The doc says, “Abstract superclass for all exceptions related to an Authentication object being invalid for whatever reason.” However, I throw it at the point of parsing the header, no Authentication object exists yet (valid or not)

2. javax.naming.AuthenticationNotSupportedException

Pros:

  • The name is right on point.
  • The javadoc matches my use case: “This exception is thrown when the particular flavor of authentication requested is not supported. For example, if the program is attempting to use strong authentication but the directory/naming supports only simple authentication, this exception would be thrown. Identification of a particular flavor of authentication is provider- and server-specific. It may be specified using specific authentication schemes such those identified using SASL, or a generic authentication specifier (such as “simple” and “strong”).”

Cons:

  • The exception is a subtype of NamedException. It has these public methods: Name getResolvedName(), Name getRemainingName(), and Object getResolvedObj(). I’m not sure how I can meaningfully override them. If I don’t, part of my exception’s API is going to return “toxic” nulls
  • The class is prehistoric. Name, which I mentioned above, has a method that returns Enumeration

3. java.lang.RuntimeException

Pros:

  • Simple, no bother

Cons:

  • No semantic weight on its own. An extra catch branch is required to catch my subclass

I mean if the process of authentication can throw exceptions from different hierarchies (one library throws one exception type, another throws another exception type), you’re either stuck with an ugly multi-catch (which you have to maintain to include every exception) or you should translate each of them into one exception. It’s better if it’s from a standard library so we’re less coupled with extrenal dependencies. You should catch those exceptions separately to map them into a 401 response. At the very least, a client should know whether it’s their mess-up (4xx) or the server’s (5xx)

What do you think? What exception do you translate those exceptions into, in your work?