I am currently getting this error:
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
Which is handled by the DaoAuthenticationProvider however, it throws an InternalAuthenticationServiceException exception. This bypasses the exception handling of the ProviderManager, which does not call my customDaoProvider which would authenticate the user.
There are 2 DaoAuthenticationProvider registred with the ProviderManager. My observation is that on the first iteration of the ProviderManager, it selects DefaultAuthenticationProvider. I figure that is how it works, which would fail then the ProviderManager, on it's second Iteration would select my custom DaoAuthenticationProvider (customDaoProvider ) to verify the user credential. Thing is on the first iteration, when it fails it throws that specific error that the ProviderManager would rethrow.
This is inside the ProviderManager that would capture the specific error:
try {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
} catch (AccountStatusException e) {
prepareException(e, authentication);
// SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
throw e;
} catch (InternalAuthenticationServiceException e) {
prepareException(e, authentication);
throw e;
} catch (AuthenticationException e) {
lastException = e;
}
Note the catch for InternalAuthenticationServiceException
. Here it rethrow the exception and stop the authentication process.
My entire security.xml below (except the element):
<authentication-manager alias="authenticationManager" xmlns="http://ift.tt/1c8inpe">
<sec:authentication-provider user-service-ref="clientDetailsUserService" />
<sec:authentication-provider ref="customDaoProvider">
</sec:authentication-provider>
</authentication-manager>
<beans:bean id="customUserDetailService" class="com.xxxx.api.services.UserDetailsServiceImpl">
<beans:property name="accountService" ref="userAccountServiceImpl"></beans:property>
</beans:bean>
<!-- DAO Providers -->
<beans:bean id="customDaoProvider" class="com.xxxx.api.daoauthproviders.CustomDaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="customUserDetailService"/>
<beans:property name="passwordEncoder" ref="passwordEncoder" />
<beans:property name="accountService" ref="userAccountServiceImpl"></beans:property>
<beans:property name="clientService" ref="clientServiceImpl"></beans:property>
</beans:bean>
<!-- End of DAO Providers -->
<beans:bean id="clientDetails" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">
<beans:constructor-arg ref="dataSource" />
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://ift.tt/GArMu6">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:refresh-token />
<oauth:client-credentials/>
<oauth:custom-grant token-granter-ref="customPasswordGrant"/>
<oauth:custom-grant token-granter-ref="randomTokenGrant" />
</oauth:authorization-server>
<beans:bean id="restServicesSuccessHandler" class="com.xxxx.api.handlers.RestAuthenticationSuccessHandler" />
<oauth:resource-server id="resourceServerFilter" resource-id="api" token-services-ref="tokenServices" />
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<beans:bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="api/" />
</beans:bean>
<!-- Custom Grant Types -->
<beans:bean id="randomTokenGrant" class="com.xxxx.api.grants.RandomTokenGrant">
<beans:constructor-arg index="0"><beans:value>${api.common.login.oauth.token}</beans:value></beans:constructor-arg>
<beans:constructor-arg index="1"><beans:value>${user.login.username.param}</beans:value></beans:constructor-arg>
<beans:constructor-arg index="2"><beans:value>${user.login.password.param}</beans:value></beans:constructor-arg>
<beans:constructor-arg index="3" ref="authenticationManager"></beans:constructor-arg>
<beans:constructor-arg index="4" ref="tokenServices"></beans:constructor-arg>
<beans:constructor-arg index="5" ref="clientDetails"></beans:constructor-arg>
<beans:constructor-arg index="6"><beans:value>${api.common.login.oauth.grant_type.two_factor}</beans:value></beans:constructor-arg>
<beans:constructor-arg index="7" ref="userAccountServiceImpl"></beans:constructor-arg>
</beans:bean>
<beans:bean id="customPasswordGrant" class="com.xxxx.api.grants.CustomPasswordGrant">
<beans:constructor-arg index="0" ref="authenticationManager"></beans:constructor-arg>
<beans:constructor-arg index="1" ref="tokenServices"></beans:constructor-arg>
<beans:constructor-arg index="2" ref="clientDetails"></beans:constructor-arg>
<beans:constructor-arg index="3" ref="userAccountServiceImpl"></beans:constructor-arg>
<beans:constructor-arg index="4"><beans:value>${api.common.login.oauth.grant_type.custom_password}</beans:value></beans:constructor-arg>
</beans:bean>
<!-- End Of Custom Grant Types -->
<beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
<beans:constructor-arg ref="dataSource" />
</beans:bean>
<beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="supportRefreshToken" value="true" />
<beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>
<beans:bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="api" />
</beans:bean>
<beans:bean id="clientServiceImpl" class="com.xxxx.api.services.ClientServiceImpl">
<beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>
Aucun commentaire:
Enregistrer un commentaire