Question
I am having hard time migrating my Spring Boot 1.5.7 application to Spring Boot 2 because of some changes in Spring security and OAuth2. There were some steps described in the migration guide but they hardly describe all changes and how to work around them to keep the existing behavior.
Bug report
Previously, I had basic auth nad OAuth2 side by side implemented on my auth server - REST endpoints were secured with OAuth2 and my Thymeleaf pages secured with session. This was done using the following config:
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String LOGIN = "/login";
private static final String LOGOUT_SUCCESS = "/login?logout";
private final UserDetailsService userDetailsService;
private final AuthenticationManager authenticationManager;
public WebSecurityConfig(UserDetailsService userDetailsService, @Lazy AuthenticationManager authenticationManager) {
this.userDetailsService = userDetailsService;
this.authenticationManager = authenticationManager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// enable cors
.cors().and()
.requestMatchers().antMatchers("/oauth/**", "/*").and()
// These from the above are secured by the following way
.authorizeRequests().antMatchers("/").permitAll()
// These from the rest are secured by the following way
.anyRequest().authenticated().and()
// Set login page
.formLogin().loginPage(LOGIN).permitAll().defaultSuccessUrl("/")
// Set logout handling
.and().logout().logoutSuccessUrl(LOGOUT_SUCCESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager);
auth.userDetailsService(userDetailsService);
}
}
I was using spring-security-oauth2
package and switched to spring-security-oauth2-autoconfigure
as suggested. However, OAuth2 seems to be overriden with the basic security completely and SecurityProperties.ACCESS_OVERRIDE_ORDER
is no longer available. All REST endpoints return 302 - redirect to login (including /token
endpoint) instead of 401 without a valid token.
Could someone point out to me, how to successfuly migrate this security config?
Questions don't really belong in GitHub issues, but let's stick with this for a while and see if an update to the migration guide is warranted.
All REST endpoints return 302 - redirect to login (including /token endpoint) instead of 401 without a valid token.
This means that you either have a single misconfigured WebSecurityConfigurerAdapter
or you have more than one and one with higher precedence is overriding your OAuth security configuration. I can't tell which as you haven't shared to code that you're using with Boot 2.0.
If you'd like us to investigate further, please share a minimal, complete, and verifiable example of the problem.
Thanks for the reply. I only have this single WebSecurityAdapter that I posted as part of this question. This adapter was working in Spring Boot 1.5.7 and the only change (apart from the missing ACCESS_OVERRIDE_ORDER) was migration to Spring Boot 2.
Ok. Please turn your code snippet above into a minimal, complete, and verifiable example and we'll take things from there.
I have created an example project with replicated security configuration. There are some minor issues but it shows the behavior I was describing in my issue.
Thanks for the sample. Unfortunately, it doesn't reproduce the behaviour that you have described. For example, I get a 401 response from the token endpoint:
curl -v localhost:8000/auth/oauth/token
* Trying ::1...
* Connected to localhost (::1) port 8000 (#0)
> GET /auth/oauth/token HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 401
< Set-Cookie: JSESSIONID=BB55F9E770A2E66FC9F4F3B47ABA58E3; Path=/auth; HttpOnly
< WWW-Authenticate: Basic realm="oauth2/client"
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Mon, 05 Mar 2018 17:34:16 GMT
<
* Connection #0 to host localhost left intact
{"timestamp":"2018-03-05T17:34:16.021+0000","status":401,"error":"Unauthorized","message":"Unauthorized","path":"/auth/oauth/token"}
I only have this single WebSecurityAdapter that I posted as part of this question.
This is true for your code, but it is not true for your application has a whole. spring-security-oauth2-autoconfigure
provides ResourceServerConfiguration
which is a WebSecurityConfigurerAdapter
and has an order of 3. Your WebSecurityConfig
has no order so it's using the Spring Security default of 100. This means that it has lower precedence than ResourceServerConfiguration
and, where there's an overlap in the request matching, ResourceServerConfiguration
will win.
I tried sending a request for token and got 302 - redirect to login, instead of 401 that you described. I will send you the cUrl request once I get back to my computer.
I tried this example project I created on another computer and still got the issue I am trying to describe. It seems that you are not including the basic auth header in your request (clientId:secret which is base64 encoded acme:secret
).
See my example cUrl command below:
curl -X POST http://localhost:8000/auth/oauth/token -H 'authorization: Basic YWNtZTpzZWNyZXQ=' -H 'cache-control: no-cache' -H 'content-type: multipart/form-data' -H -F [email protected] -F password=password -F grant_type=password
This is the output:
<!DOCTYPE html>
<html lang="en">
<body>
<div id="container">
<form class="form-signin" action="/auth/login" method="post">
<input type="hidden" name="_csrf" value="c9d03931-77b9-4e7d-ac1b-79361cc31adb"/>
<h2 class="form-signin-heading">Login</h2>
<div class="form-group input-group">
<span class="input-group-addon">
<span class="glyphicon glyphicon-envelope"></span>
</span>
<input
type="email"
id="username"
class="form-control"
placeholder="email"
name="username"
required="required" autofocus="autofocus" />
</div>
<div class="form-group input-group">
<span class="input-group-addon">
<span class="glyphicon glyphicon-lock"></span>
</span>
<input
type="password"
id="inputPassword"
class="form-control"
placeholder="password"
name="password" required="required" />
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">login</button>
</form>
</div>
</body>
</html>
Expected behavior is to receive either 401 with non-matching credentials or 200 with token as the response.
Thanks. Not sure if I missed it above, but it would have saved a considerable amount of time if you had said that you were getting a 302 when you provided basic auth credentials.
I can now reproduce the behaviour that you've described and it's because your client secret isn't encoded using BCrypt which is what Spring Security 5 requires by default. You can see an indication of this in the logs:
2018-03-07 10:10:28.904 WARN 68489 --- [nio-8000-exec-4] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
This can be corrected by updating V1_1__Test_Data.sql
:
diff --git a/src/main/resources/db/development/V1_1__Test_Data.sql b/src/main/resources/db/development/V1_1__Test_Data.sql
index f741085..6f219db 100644
--- a/src/main/resources/db/development/V1_1__Test_Data.sql
+++ b/src/main/resources/db/development/V1_1__Test_Data.sql
@@ -5,4 +5,4 @@ INSERT INTO users (user_id, username, password) VALUES
INSERT INTO oauth_client_details (client_id, resource_ids, client_secret, scope,
authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity,
refresh_token_validity, additional_information, autoapprove) VALUES
- ('acme', 'resource', 'secret', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');
\ No newline at end of file
+ ('acme', 'resource', '$2a$10$s7rR9qxaUnOJaE3J6ZSICupQxm.xTJhvScmXV.ylsI3AIY5OMXp.q', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');
\ No newline at end of file
This curl request is now able to authenticate:
curl -X POST http://localhost:8000/auth/oauth/token -H 'authorization: Basic YWNtZTpzZWNyZXQ=' -H 'cache-control: no-cache' -H 'content-type: multipart/form-data' -F [email protected] -F password=password -F grant_type=password
However, the request fails when trying to get an access token:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.authentication.AuthenticationManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.context.annotation.Lazy(value=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1509) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver$1.getTarget(ContextAnnotationAutowireCandidateResolver.java:90) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at com.sun.proxy.$Proxy96.authenticate(Unknown Source) ~[na:na]
at org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter.getOAuth2Authentication(ResourceOwnerPasswordTokenGranter.java:71) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.getAccessToken(AbstractTokenGranter.java:70) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.grant(AbstractTokenGranter.java:65) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.CompositeTokenGranter.grant(CompositeTokenGranter.java:38) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
at org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer$4.grant(AuthorizationServerEndpointsConfigurer.java:561) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(TokenEndpoint.java:132) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:870) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:776) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:215) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.28.jar:8.5.28]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.28.jar:8.5.28]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]
This happens because there's no AuthenticationManager
bean in your application. You can expose one with this change that is described in the migration guide:
diff --git a/src/main/java/com/smedzl/example/config/WebSecurityConfig.java b/src/main/java/com/smedzl/example/config/WebSecurityConfig.java
index f8f2af0..ccfc0ec 100644
--- a/src/main/java/com/smedzl/example/config/WebSecurityConfig.java
+++ b/src/main/java/com/smedzl/example/config/WebSecurityConfig.java
@@ -1,5 +1,6 @@
package com.smedzl.example.config;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
@@ -55,4 +56,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
auth.userDetailsService(userDetailsService);
}
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
}
You then hit a problem because the password isn't correctly encoded. This can be corrected with another update to V1_1__Test_Data.sql:
diff --git a/src/main/resources/db/development/V1_1__Test_Data.sql b/src/main/resources/db/development/V1_1__Test_Data.sql
index f741085..48a7a6c 100644
--- a/src/main/resources/db/development/V1_1__Test_Data.sql
+++ b/src/main/resources/db/development/V1_1__Test_Data.sql
@@ -1,8 +1,8 @@
INSERT INTO users (user_id, username, password) VALUES
- ('1', '[email protected]', 'password'),
- ('2', '[email protected]', 'password');
+ ('1', '[email protected]', '$2a$10$1XqtAJZ9EXiuCCK2gy6gTuUEyYFsB97g5op1AXxRHQibf2mNe4x0i'),
+ ('2', '[email protected]', '$2a$10$1XqtAJZ9EXiuCCK2gy6gTuUEyYFsB97g5op1AXxRHQibf2mNe4x0i');
INSERT INTO oauth_client_details (client_id, resource_ids, client_secret, scope,
authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity,
refresh_token_validity, additional_information, autoapprove) VALUES
- ('acme', 'resource', 'secret', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');
\ No newline at end of file
+ ('acme', 'resource', '$2a$10$s7rR9qxaUnOJaE3J6ZSICupQxm.xTJhvScmXV.ylsI3AIY5OMXp.q', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');
With these changes in place, a token is granted:
$ curl -X POST http://localhost:8000/auth/oauth/token -H 'authorization: Basic YWNtZTpzZWNyZXQ=' -H 'cache-control: no-cache' -H 'content-type: multipart/form-data' -F [email protected] -F password=password -F grant_type=password
{"access_token":"8f6d7f22-db8e-4799-b45a-c856bc9c766e","token_type":"bearer","refresh_token":"d622e5fa-78c4-45f9-8396-2ab50b4cdff6","expires_in":3599,"scope":"read write"}
Excellent response. I did not know about these changes in Spring Security 5. It still puzzles me a bit why wrong basic auth clientId:secret credentials result in 302 instead of 401 but apart from that, it works fine. I can proceed witht the migration to Spring Boot 2 now.
Thank you very much!
It still puzzles me a bit why wrong basic auth clientId:secret credentials result in 302 instead of 401
IIRC, from when I was debugging this, the request is forwarded to /error
which is secured with form login so you end of with a 302 redirecting you to the login page.
Thanks @Smedzlatko !! You helped with my problem, which was the same.
Can anyone comment on the removal of SecurityProperties.ACCESS_OVERRIDE_ORDER in Spring 2.0
What is the impact?
@Datta4400 We prefer not to use the issue tracker for questions, please join us on gitter.im or ask on stackoverflow.com. You might also want to check out the migration guide.
Most helpful comment
Can anyone comment on the removal of SecurityProperties.ACCESS_OVERRIDE_ORDER in Spring 2.0
What is the impact?