Spring-boot oauth2 /oauth/token 404 - spring

so I have an existing SpringBoot project.
a) I added this at the top of my main #Configuration class
#Import({ WebSecurityConfiguration.class, OAuth2ServerConfiguration.class })
b) The contents of the above 2 classes are the same as what is in this project: https://github.com/royclarkson/spring-rest-service-oauth/tree/master/src/main/java/hello
c) I startup my app and see this as expected in the logs:
2015-10-28 20:05:40,037 INFO [FrameworkEndpointHandlerMapping] Mapped "{[/oauth/authorize]}" onto 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)
2015-10-28 20:05:40,037 INFO [FrameworkEndpointHandlerMapping] Mapped "{[/oauth/authorize],methods=[POST],params=[user_oauth_approval]}" onto public org.springframework.web.servlet.View org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.approveOrDeny(java.util.Map<java.lang.String, java.lang.String>,java.util.Map<java.lang.String, ?>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)
2015-10-28 20:05:40,040 INFO [FrameworkEndpointHandlerMapping] Mapped "{[/oauth/token],methods=[GET]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
2015-10-28 20:05:40,040 INFO [FrameworkEndpointHandlerMapping] Mapped "{[/oauth/token],methods=[POST]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
2015-10-28 20:05:40,041 INFO [FrameworkEndpointHandlerMapping] Mapped "{[/oauth/check_token]}" onto public java.util.Map<java.lang.String, ?> org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.checkToken(java.lang.String)
2015-10-28 20:05:40,041 INFO [FrameworkEndpointHandlerMapping] Mapped "{[/oauth/confirm_access]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint.getAccessConfirmation(java.util.Map<java.lang.String, java.lang.Object>,javax.servlet.http.HttpServletRequest) throws java.lang.Exception
2015-10-28 20:05:40,042 INFO [FrameworkEndpointHandlerMapping] Mapped "{[/oauth/error]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint.handleError(javax.servlet.http.HttpServletRequest)
d) When I go to /greeting I get the following as expected:
{ "error": "unauthorized", "error_description": "Full authentication is required to access this resource" }
e) When I attempt to POST to /oauth/token I see the below in the logs... but I get a 404 and no token back. This has been driving me nuts now for 2 days trying to figure this out. Any help appreciated.
2015-10-28 20:08:59,713 DEBUG [FilterSecurityInterceptor] Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2015-10-28 20:08:59,713 DEBUG [FilterSecurityInterceptor] Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#7159411d: Principal: org.springframework.security.core.userdetails.User#8e81ee76: Username: clientapp; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: USER
2015-10-28 20:08:59,713 DEBUG [AffirmativeBased] Voter: org.springframework.security.web.access.expression.WebExpressionVoter#44aef1f8, returned: 1
2015-10-28 20:08:59,713 DEBUG [FilterSecurityInterceptor] Authorization successful
2015-10-28 20:08:59,713 DEBUG [FilterSecurityInterceptor] RunAsManager did not change Authentication object
2015-10-28 20:08:59,713 DEBUG [FilterChainProxy] /oauth/token reached end of additional filter chain; proceeding with original chain
2015-10-28 20:08:59,714 DEBUG [ExceptionTranslationFilter] Chain processed normally
2015-10-28 20:08:59,714 DEBUG [SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed
Again, I just get a 404

The problem is you are not adding Authorization in the header.Without adding header you cannot access the resources, and sometimes it shows error of Bad Credentials.For postman POST call for /oauth/token at there authorization is needed in header.
If i am not adding any authorization to the header.It shows me following error:-
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
You can create Authorization with the help of Base64Encoder

The problem was that in my main #Configuration annotated class I had a dispatcherServlet #Bean registered, which was intercepting all the requests. Once I changed the method name to something other than dispatcherServlet() it fixed the issue:
BAD:
#Bean
public ServletRegistrationBean dispatcherServlet() {
CXFServlet cxfServlet = new CXFServlet();
return new ServletRegistrationBean(cxfServlet, "/x/*");
}
GOOD:
#Bean
public ServletRegistrationBean thisFixedMyIssue() {
CXFServlet cxfServlet = new CXFServlet();
return new ServletRegistrationBean(cxfServlet, "/x/*");
}

Related

Spring boot OAuth2RestTemplate client setup, authorization_request_not_found error

I try to setup an OAuth2RestTemplate in a spring boot project. I tried to follow a custom setup, but for some reason I always get authorization_request_not_found error when trying to access a secured resource.
My AppConfig:
#EnableOAuth2Client
#SpringBootApplication
public class AppConfig {
public static void main(String[] args) {
SpringApplication.run(AppConfig.class, args);
}
#Bean
RestTemplate restTemplate(OAuth2ProtectedResourceDetails oauth2RemoteResource) {
return new OAuth2RestTemplate(oauth2RemoteResource);
}
}
SecurityConfig:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.mvcMatchers("/", "/login/**").permitAll()
.mvcMatchers("/secure").authenticated()
.anyRequest().permitAll()
.and()
.oauth2Login()
.and()
.oauth2Client();
}
}
Controller:
#GetMapping("/secure")
public String secure() {
Object result = restTemplate.getForObject("https://esi.evetech.net/latest/alliances", Object.class);
return "/";
}
application.yml:
security:
oauth2:
client:
id: eve
client-id: clientId
client-secret: secret
grant-type: authorization_code
user-authorization-uri: https://login.eveonline.com/v2/oauth/authorize
access-token-uri: https://login.eveonline.com/v2/oauth/token
pre-established-redirect-uri: http://localhost:8080/login/oauth2/code/eve
use-current-uri: false
scope:
- esi-characters.read_blueprints.v1
resource:
user-info-uri: https://login.eveonline.com/oauth/verify
spring:
security:
oauth2:
client:
registration:
eve:
authorization-grant-type: authorization_code
client-id: clientId
client-secret: secret
redirect-uri: http://localhost:8080/login/oauth2/code/eve
client-authentication-method: basic
scope:
- esi-characters.read_blueprints.v1
provider:
eve:
authorization-uri: https://login.eveonline.com/v2/oauth/authorize
token-uri: https://login.eveonline.com/v2/oauth/token
user-info-uri: https://login.eveonline.com/oauth/verify
user-name-attribute: CharacterID
Now I find this also interesting since I am not sure why I have to declare these properties twice.
I mean the OAuth2RestTemplate takes an AuthorizationCodeResourceDetails instance in the constructor in AppConfig which reads the security.oatuh2.client properties, while the DefaultOAuth2ClientContext inside the OAuth2RestTemplate constructor reads the other, I just don't understand why is it like that? Is there a simple setup?
Anyway going back to the original problem, when I access /secure it redirects me to the login page, where I login successfully which then redirects me back to the /secure page, so far so good.
Just before calling the restTemplate, I have this in the log:
2020-05-06 22:55:31.528 DEBUG 29177 --- [nio-8080-exec-4] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /secure; Attributes: [authenticated]
2020-05-06 22:55:31.528 DEBUG 29177 --- [nio-8080-exec-4] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken#3bb07c9: Principal: Name: [<ID>], Granted Authorities: [[ROLE_USER, SCOPE_esi-characters.read_blueprints.v1]], User Attributes: [{CharacterID=<ID>, CharacterName=<Name>, ExpiresOn=2020-05-06T22:15:31, Scopes=esi-characters.read_blueprints.v1, TokenType=Character, CharacterOwnerHash=<Hash>, IntellectualProperty=EVE}]; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 472A39D41FE34AC90781A80E39E4A52D; Granted Authorities: ROLE_USER, SCOPE_esi-characters.read_blueprints.v1
2020-05-06 22:55:31.529 DEBUG 29177 --- [nio-8080-exec-4] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#47a65378, returned: 1
But after the restTemplate is called:
2020-05-06 23:00:31.482 DEBUG 29177 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Failed to complete request: org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
2020-05-06 23:00:31.483 DEBUG 29177 --- [nio-8080-exec-4] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#205366de
2020-05-06 23:00:31.483 DEBUG 29177 --- [nio-8080-exec-4] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2020-05-06 23:00:31.484 DEBUG 29177 --- [nio-8080-exec-4] o.s.s.web.DefaultRedirectStrategy : Redirecting to 'https://login.eveonline.com/v2/oauth/authorize?client_id=<clientId>&redirect_uri=http://localhost:8080/login/oauth2/code/eve&response_type=code&scope=esi-characters.read_blueprints.v1&state=<state>'
As you can see it takes me back to the login page, so I login back again and this time I get the error: [authorization_request_not_found]
log:
2020-05-06 23:02:27.285 DEBUG 29177 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /login/oauth2/code/eve?code=<code>&state=<state> at position 8 of 17 in additional filter chain; firing Filter: 'OAuth2LoginAuthenticationFilter'
2020-05-06 23:02:27.285 DEBUG 29177 --- [nio-8080-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login/oauth2/code/eve'; against '/login/oauth2/code/*'
2020-05-06 23:02:27.285 DEBUG 29177 --- [nio-8080-exec-6] .s.o.c.w.OAuth2LoginAuthenticationFilter : Request is to process authentication
2020-05-06 23:02:27.287 DEBUG 29177 --- [nio-8080-exec-6] .s.o.c.w.OAuth2LoginAuthenticationFilter : Authentication request failed: org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found]
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found]
at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:163) ~[spring-security-oauth2-client-5.2.2.RELEASE.jar:5.2.2.RELEASE]
I am lost at this point, not sure why I am getting this.
I also uploaded the project to github in case it's easier to check out what's wrong with it.
Thanks

AnonymousAuthenticationFilter intercepts request after successful login with Custom Authentication Provider

We have a CustomAuthenticationProvider(AuthenticationProvider) developed for Spring which works with CustomAuthenticationRequest(Authentication), CustomAuthentication(Authentication), a CustomUser.
Once we validate credentials when our Controller is invoked we create a CustomAuthenticationRequest based on the credentials.
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(new CustomAuthenticationRequest(new CustomUser(account.getUsername())));
Debug login confirms that the CustomAuthenticationRequest has been stored in the HTTPSession.
HttpSessionSecurityContextRepository - SecurityContext 'org.springframework.security.core.context.SecurityContextImpl#730db7d8: Authentication: pro.someplace.spring.CustomAuthenticationRequest#730db7d8' stored to HttpSession: 'org.apache.catalina.session.StandardSessionFacade#5da80010
The WebSecurityConfigurerAdapter registers our AuthenticationProvider:
#Override
public void configure(AuthenticationManagerBuilder builder)
throws Exception {
builder.authenticationProvider(new CustomAuthenticationProvider());
}
And establishes what can and cannot be seen by anonymous and authenticated users.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login", "/registration").permitAll()
.anyRequest()
.authenticated();
}
The problem we have is that before the FilterSecurityInterceptor can consult which AuthenticationProvider is appropriate the AnonymousAuthenticationFilter steps in:
o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#4cc1f847: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: 74DB809F1CB5CFB1F977EC20B37B218E; Granted Authorities: ROLE_ANONYMOUS'
If I remove the AnonymousAuthenticationFilter then I cannot access permitAll() in the configuration (different error).
Curiously, I notice this logging message at the end of request processing:
SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
Ok. So the SecurityContextPersistenceFilter should have persisted the context in the HttpSessionSecurityContextRepository.
But when the next request appears the SecurityContextPersistenceFilter has no such object. Was it saved at all? Was it removed?
o.s.security.web.FilterChainProxy - /ordervalidator at position 2 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
How can I configure spring to allow authenticated users where I want them and use my CustomAuthenticationProvider when available in the HTTPSession? Where is the security object and why is it not being stored?
And so will be as dumb as it sounds. The front end is React and so we were returning a cookie to the front end however the front end was not being returned to us. As soon as I manually insert cookies into requests I have trapped in either (Postman or Burp) my Context can be found.
This is a cautionary tale as there is a generational difference between the frontend React and the backend (Spring) developers. The backend expect cookies and this is assumed, the front end "...have no idea why we would want them and its a bad idea".

Never go in WebSecurityConfigurerAdapter

I made a simple rest service and I wanted to add a simple security on the api.
So I created an WebSecurityConfigurerAdapter :
package org.test.subscription.webservice.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("test1").password("test1").roles("superAdminRole").and()
.withUser("test2").password("test2").roles("superAdminRole");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests()
.anyRequest().hasRole("webserviceReadRole").and()
.csrf().disable();
}
}
And this is my main runner:
package org.test.subscription.webservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
But when I call something inside my API,I'm not authenticate at all, and I get my "hello world" response. So he never check my role. Any ideas why?
Your example should work as you expect it (tested in boot 1.5.7 and also 2.0.0 M3). So I would recommend that you try the following. First verify some trivial things:
That you do not have anything that disables security checks in your application.properties or the corresponding yaml (e.g. something like security.ignored and Co.).
That you do not have another WebSecurityConfigurerAdapter in your application.
That your classes are scanned correctly by Spring.
That you do not have some strange cookies in the browser. E.g. try the same request by starting the browser in private mode or use curl or something similar.
If it still does not work enable the Spring Security debugger for a deeper insight on what is going on under the hood and why you see unexpected behavior. This may be achieved in the following way:
#EnableWebSecurity(debug = true)
This will hint Spring to print lots of extra details which will help you find out what is wrong. In your setup you should see something like the following in the logs when you issue an request.
First, the request itself with the proper headers. Example with the most important parts:
Request received for GET '/path/to/your/api':
org.apache.catalina.connector.RequestFacade#58a4ad1c
authorization: Basic dGVzdDE6dGVzdDE=
cookie: JSESSIONID=9E4EBB889BB178E05446104EF2787C2F
Then you will see the filter chain managed by the FilterChainProxy and matched with your request (note that there might be other filter chains depending on the setup of your app - the log shows the matched chain which may not be the one that you expect):
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
Then lots of DEBUG messages will follow in the log. Please pay special attention to the messages created around the BasicAuthenticationFilter:
2017-10-07 14:42:21.644 DEBUG 56071 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /pat/to/your/api at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-10-07 14:42:21.645 DEBUG 56071 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'test1'
2017-10-07 14:42:21.645 DEBUG 56071 --- [nio-8080-exec-2] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2017-10-07 14:42:21.647 DEBUG 56071 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#8fc16c08: Principal: org.springframework.security.core.userdetails.User#6924ddf: Username: test1; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_superAdminRole; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 9E4EBB889BB178E05446104EF2787C2F; Granted Authorities: ROLE_superAdminRole
2
And also to the FilterSecurityInterceptor which should output the successful authorization message:
2017-10-07 14:42:21.649 DEBUG 56071 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#8fc16c08: Principal: org.springframework.security.core.userdetails.User#6924ddf: Username: test1; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_superAdminRole; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 9E4EBB889BB178E05446104EF2787C2F; Granted Authorities: ROLE_superAdminRole
2017-10-07 14:42:21.649 DEBUG 56071 --- [nio-8080-exec-2] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#1ca8b2d, returned: 1
2017-10-07 14:42:21.649 DEBUG 56071 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
Armed with all these details approach SO further :-)

Spring Boot: Oauth2: Access is denied (user is anonymous); redirecting to authentication entry point

I am trying to use spring boot oauth2 to accomplish stateless authentication and authorisation. However, I am struggling to it working.
Here is my code:
#EnableAutoConfiguration
#ComponentScan
//#EnableEurekaClient
//#EnableZuulProxy
#Configuration
public class AuthServiceApp {
public static void main(String[] args) {
SpringApplication.run(AuthServiceApp.class, args);
}
}
Authorisation Config:
#Configuration
#EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager auth;
#Autowired
private DataSource dataSource;
#Autowired
private CustomUserDetailsService userDetailService;
#Autowired
private ClientDetailsService clientDetailsService;
#Bean
public JdbcTokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// #OFF
endpoints
.authorizationCodeServices(authorizationCodeServices())
.authenticationManager(auth)
.userDetailsService(userDetailService)
.tokenStore(tokenStore());
// #ON
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// #OFF
clients.jdbc(dataSource)
.withClient("client")
.secret("secret")
.authorizedGrantTypes("password","refresh_token", "client_credentials")
.authorities("USER")
.scopes("read", "write")
.autoApprove(true)
.accessTokenValiditySeconds(60)
.refreshTokenValiditySeconds(300);
// #ON
}
}
Resource Server Config:
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
#Autowired
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
#Override
public void configure(HttpSecurity http) throws Exception {
// #OFF
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint)
.and()
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
.csrf()
// .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
.disable()
.headers()
.frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers("/identity/**").authenticated();
// #ON
}
}
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #OFF
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
// #ON
}
}
Controller:
#RestController
#RequestMapping("/")
public class AuthController {
#PreAuthorize("#oauth2.hasScope('read')")
#GetMapping("/user")
public Principal getUser(Principal user) {
return user;
}
}
I can get the access token using POSTMAN. I am using the same access token in the header to get the user details as http://localhost:8082/identity/user before it gets expired. However, I get login page html response with following log on console:
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 301C6EDD36372CF9C553FCFCD4AA47E3; Granted Authorities: ROLE_ANONYMOUS'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy : /user at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy : /user at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy : /user at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/user'; against '/login'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /user; Attributes: [authenticated]
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 301C6EDD36372CF9C553FCFCD4AA47E3; Granted Authorities: ROLE_ANONYMOUS
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#55b4f25d, returned: -1
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]
But it seems like I have been authenticated when making first call to get the access token to oauth/token:
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#50c8f5e8: Principal: org.springframework.security.core.userdetails.User#af12f3cb: Username: client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 2F070B741A55BD1E47933621D9127780; Granted Authorities: USER
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#61f8721f, returned: 1
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.security.web.FilterChainProxy : /oauth/token reached end of additional filter chain; proceeding with original chain
2017-05-24 22:54:35.967 DEBUG 16899 --- [nio-8082-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/token
2017-05-24 22:54:35.968 DEBUG 16899 --- [nio-8082-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException]
2017-05-24 22:54:35.975 DEBUG 16899 --- [nio-8082-exec-6] .o.p.p.ResourceOwnerPasswordTokenGranter : Getting access token for: client
2017-05-24 22:54:35.975 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
Hibernate: select user0_.id as id1_1_, user0_.enabled as enabled2_1_, user0_.name as name3_1_, user0_.password as password4_1_, user0_.username as username5_1_ from user user0_ where user0_.username=?
Hibernate: select roles0_.user_id as user_id1_2_0_, roles0_.role_id as role_id2_2_0_, role1_.id as id1_0_1_, role1_.role as role2_0_1_ from user_role roles0_ inner join role role1_ on roles0_.role_id=role1_.id where roles0_.user_id=?
2017-05-24 22:54:36.125 INFO 16899 --- [nio-8082-exec-6] o.s.s.o.p.token.store.JdbcTokenStore : Failed to find access token for token 180c2528-b712-4088-9cce-71e9cc7ccb94
2017-05-24 22:54:36.232 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2017-05-24 22:54:36.232 DEBUG 16899 --- [nio-8082-exec-6] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
May be I am configuring something wrong. What am I missing here?
I had a similar issue and found that the OAuth2AuthenticationProcessingFilter was not getting invoked by the filter chain and because of which, user was not getting authenticated and hence treated as anonymous.
Am using Spring-boot 1.5.3 version and I added below line in application.yml to fix the ordering.
security.oauth2.resource.filter-order=3
There must be a log statement present which shows that its getting invoked
DEBUG 34386 --- [nio-8082-exec-1] o.s.security.web.FilterChainProxy : /foo at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
Reference - https://github.com/spring-projects/spring-security-oauth/issues/993
To use
.authorizedGrantTypes("password","refresh_token", "client_credentials")
you need to open access to
/auth/token
in security configuration of your Authorization Server
#Override
protected void configure(HttpSecurity http) throws Exception {
code...
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.anyRequest().authenticated()
code...
}
I was facing the same problem and managed to fix it by explicitly disabling some spring autoconfiguration:
#EnableAutoConfiguration(exclude = [OAuth2AutoConfiguration::class,
SecurityAutoConfiguration::class, SecurityFilterAutoConfiguration::class])
Also check if you are using multiple OAuth2 filters coming from multiple auth-related dependices/libraries.
In my case I was using
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
Along with another custom OAuth2 library used in my organization, which caused the spring library to attempt to authenticate before the custom (correct) one, and with no credentials fed to it of course throwing this exact exception.
My service calls worked once I removed the Spring OAuth2 dependency.

Custom ConstraintValidator is called even if user role not listed in #PreAuthorize

I have a Spring Boot app with POST endpoint, #PreAuthorize role definition and a custom validator for the request body:
#PreAuthorize("hasAnyRole('ROLE_OTHER')")
#RequestMapping(value = "post", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public String post(#RequestBody #Valid DummyDTO dummyDTO) {
...
}
1) When I call the endpoint with wrong role and non-valid request body the custom validation code i.e. ConstraintValidator.isValid() is executed and I got 400 Bad Request.
2) When I call the endpoint with wrong role and valid request body the custom validation code i.e. ConstraintValidator.isValid() is executed and I got 403 Forbidden.
Why is the custom validation code executed before the #PreAuthorize check? I would expect to get 403 in both cases.
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor : Successfully Authenticated: org.springframework.security.authentication.TestingAuthenticationToken#bbd5887f: Principal: key; Credentials: [PROTECTED]; Authenticated: false; Details: null; Granted Authorities: ROLE_USER
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#41ba74ef, returned: 1
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
DEBUG 12776 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /post reached end of additional filter chain; proceeding with original chain
INFO 12776 --- [nio-8080-exec-3] com.example.DummyValidator : > isValid(): [valid]
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.a.i.a.MethodSecurityInterceptor : Secure object: ReflectiveMethodInvocation: public java.lang.String com.example.MyController.post(com.example.DummyDTO); target is of class [com.example.MyController]; Attributes: [[authorize: 'hasAnyRole('ROLE_OTHER')', filter: 'null', filterTarget: 'null']]
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.TestingAuthenticationProvider
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.a.i.a.MethodSecurityInterceptor : Successfully Authenticated: org.springframework.security.authentication.TestingAuthenticationToken#bbd5887f: Principal: key; Credentials: [PROTECTED]; Authenticated: false; Details: null; Granted Authorities: ROLE_USER
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter#356a19a2, returned: -1
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.access.vote.RoleVoter#7290b3e0, returned: 0
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.access.vote.AuthenticatedVoter#16f3e525, returned: 0
DEBUG 12776 --- [nio-8080-exec-3] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
...
My DTO:
public class DummyDTO {
#DummyConstraint
private String name;
...
}
constraint:
#Documented
#Retention(RUNTIME)
#Target({TYPE, FIELD, PARAMETER, ANNOTATION_TYPE})
#Constraint(validatedBy = {DummyValidator.class})
public #interface DummyConstraint {
...
}
and validator:
public class DummyValidator implements ConstraintValidator<DummyConstraint, String> {
private static final Logger LOGGER = LoggerFactory.getLogger(DummyValidator.class);
#Override
public void initialize(DummyConstraint constraintAnnotation) {
}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
LOGGER.info("> isValid(): [{}]", value);
return "valid".equalsIgnoreCase(value);
}
}

Resources