Spring Security Authentication Provider autenticate()’s reason for returning null

Lately, I was studying Spring security’s Authentication provider.

In the authenticate() method the docs say, “May return null if the AuthenticationProvider is unable to support authentication of the passed Authentication object. In such a case, the next AuthenticationProvider that supports the presented Authentication class will be tried.

We have another method supports() that indicates that if this provider supports the type of authentication or not.

As far as I know “AuthenticationManager” first calls supports() to check if the provider supports this type or not. Then the authenticate() method is called. So, from my understanding authenticate is only called when the provider supports it.

So, My question is ” If the provider supports this type of auth, then why should it return null from authenticating ()? and why do the docs say “May return null if the AuthenticationProvider is unable to support authentication of the passed Authentication object” ??? Should it not always support it? (Because we checked its compatibility via supports().)

Can you give an example where the provider needs to return null?

Thanks in advance.

Answer

quote from Spring Security in Action by Laurentiu Spilca

The second method in the AuthenticationProvider interface is supports-
(Class<?> authentication). You can implement this method to return
true if the current AuthenticationProvider supports the type provided
as an Authentication object. Observe that even if this method returns
true for an object, there is still a chance that the authenticate()
method rejects the request by returning null. Spring Security is
designed like this to be more flexible and to allow you to implement
an AuthenticationProvider that can reject an authentication request
based on the request’s details, not only by its type.

and its analogy I think clear things up.

An analogy of how the authentication manager and authentication
provider work together to validate or invalidate an authentication
request is having a more complex lock for your door. You can open this
lock either by using a card or an old fashioned physical key
. The lock itself is the authentication manager that decides whether to open the door. To make that decision, it delegates to the
two authentication providers: one that knows how to validate the card
or the other that knows how to verify the physical key. If you present
a card to open the door, the authentication provider that works only with physical keys complains that it doesn’t know this kind of authentication.
But the other provider supports this kind of authentication and verifies whether the
card is valid for the door. This is actually the purpose of the supports() methods.
Besides testing the authentication type, Spring Security adds one more layer for
flexibility. The door’s lock can recognize multiple kinds of cards. In this case, when
you present a card, one of the authentication providers could say, “I understand this
as being a card. But it isn’t the type of card I can validate!” This happens when supports() returns true but authenticate() returns null.

enter image description here