We have an application which is using spring-security-oauth2:1.0
. I was trying to change it to a newer version, spring-security-oauth2:2.0.7.RELEASE
. Some classes were removed, some package structure is changed, I managed to sort out all those things and I was able to start the server without any issue. But I am facing a strange issue here.
With OAuth2 - 1.0 version
, when the user logs in we used to do a GET
request on /oauth/token
, For example :
http://localhost:8080/echo/oauth/token?grant_type=password&client_id=ws&client_secret=secret&scope=read,write&[email protected]&password=password123
and It used to work just fine.
When I try the same thing, First of all I am not able to make a GET
request because of the logic in TokenEndPoint.java
private Set<HttpMethod> allowedRequestMethods = new HashSet<HttpMethod>(Arrays.asList(HttpMethod.POST));
@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!allowedRequestMethods.contains(HttpMethod.GET)) {
throw new HttpRequestMethodNotSupportedException("GET");
}
return postAccessToken(principal, parameters);
}
I have tried to make a POST
request same as above URL, but I get InsufficientAuthenticationException
with the error message
There is no client authentication. Try adding an appropriate authentication filter
This is because of the following POST
request controller in TokenEndpoint.java
. When I debug, I see that principal
is null.
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
//principal is null here
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
.............
}
I have an authentication filter and it worked well when I used version 1.0
. This is the relevant prats of my config:
<authentication-manager xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="userDetailsService"/>
</authentication-manager>
<bean id="userDetailsService" class="com.hcl.nc.service.UserDetailsService">
<constructor-arg><ref bean="sessionFactory" /></constructor-arg>
</bean>
I always thought that the request will be authenticated by authentication-provider
and goes to token-endpoint
but that does not seem to be the correct flow. After debugging the application with version 2.0.7
, now I really doubt my understanding about the flow.
Could somebody please explain why it worked in previous version and why it's not working now?
Do I have do to something different to get a OAuth token??
NOTE: I have already checked these questions : here, here, here. But I was not able to find the correct solution.
I don't know the previous version, but I know a bit about 2.0.7.
I suspect your problem is that your TokenEndpoint security tries to authenticate your clients against your user service.
The TokenEndpoint is protected by a BasicAuthenticationFilter
. By default this filter would use an AuthenticationManager
instance, which itself holds an AuthenticationProvider
, which itself depends on an instance of UserDetailsService
.
The trick is that this particular instance of UserDetailsService
must be client based, not user based : that's why there is a ClientDetailsUserDetailsService
, which adapts ClientDetailsService
to UserDetailsService
.
Normally all this stuff is already done by default when you use the framework's configuration classes AuthorizationServerConfigurerAdapter
, @EnableAuthorizationServer
, etc..
I had the same problem and my application.yml had this line:
servlet:
path: /auth
so the token address was: /auth/oauth/token
I remove the path from application.yml so the token path became:
/oauth/token
And everything works fine.
I hope this help
One of the problems of the following error, can be that authentication was not performed. I have encountered this problem with older implementation of Spring.
verify that:
TokenEndpoint -> postAccessToken method. Check if Principal is not null. If it is null it means that Basic Authroziation was not performed.
One of the solution to add filter was to use:
@Configuration
public class FilterChainInitializer extends AbstractSecurityWebApplicationInitializer {
}
More information about AbstractSecurityWebApplicationInitializer can be found in Spring docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With