Reputation: 635
I have an API I want to secure with OAuth2. I already did a dummy test with the password grant_type and everything works. I can request tokens, access secured endpoints with it, etc. The server acts as the authorization and resource server.
Later on I read that I should be using the implicit grant_type as the client will be a javascript app.
My client is configured like so:
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {// @formatter:off
clients
.inMemory().withClient("web")
.redirectUris("http://localhost:3000")
.secret("secret")
.authorizedGrantTypes("implicit", "refresh_token").scopes("read", "write")
.accessTokenValiditySeconds(3600).refreshTokenValiditySeconds(2592000);
}
If I try accessing the endpoint like this: http://localhost:8080/oauth/authorize?grant_type=implicit&client_id=web&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A3000
I get this:
{
"timestamp": 1464136960414,
"status": 403,
"error": "Forbidden",
"message": "Expected CSRF token not found. Has your session expired?",
"path": "/oauth/authorize"
}
How can I have a CSRF token if it's the first time I'm calling the API? If (just for testing) I disable csrf then I get this:
{
"timestamp": 1464136840865,
"status": 403,
"error": "Forbidden",
"exception": "org.springframework.security.authentication.InsufficientAuthenticationException",
"message": "Access Denied",
"path": "/oauth/authorize"
}
Setting the client with the password grant_type I'm able to make this call and everything works: http://localhost:8080/oauth/token?grant_type=password&username=test&password=123 And adding the Authorization Basic header with the client id/secret.
Just to clarify, the idea is to have this unique trusted client. So the user should just input login/password without asking the user to grant access rights to the app.
Sorry if this is a dumb question. I've been reading everything I can find but cannot seem to make progress with it.
Thanks!
EDIT:
My Spring Security Config:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MongoDBAuthenticationProvider authenticationProvider;
@Autowired
public void globalUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
My OAuth Config:
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory().withClient("web")
.redirectUris("http://localhost:3000")
.secret("secret")
.authorizedGrantTypes("implicit", "refresh_token").scopes("read", "write")
.accessTokenValiditySeconds(3600).refreshTokenValiditySeconds(2592000);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
Exception in Server:
2016-05-25 19:52:20.744 DEBUG 34968 --- [nio-8080-exec-5] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/authorize
2016-05-25 19:52:20.744 DEBUG 34968 --- [nio-8080-exec-5] .s.o.p.e.FrameworkEndpointHandlerMapping : Returning handler method [public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.String>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)]
2016-05-25 19:52:20.746 DEBUG 34968 --- [nio-8080-exec-5] o.s.s.w.a.ExceptionTranslationFilter : Authentication exception occurred; redirecting to authentication entry point
org.springframework.security.authentication.InsufficientAuthenticationException: User must be authenticated with Spring Security before authorization can be completed.
at org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(AuthorizationEndpoint.java:138) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_40]
....
Upvotes: 0
Views: 1648
Reputation: 2943
When you call the authorization server for implicit grant type you have to include an opaque string value as state parameter to avoid csrf attacks. So, the request url to the authorization server will look like:
The value you mentioned in the state parameter will be echoed back to you in the response. You then compare the echoed value with initial value to confirm that there is no csrf attack happened.
Thank you, Soma.
Upvotes: 1