Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring Sec 5 /Boot 2 + custom WebSecurityConfigurerAdapter -http.oauth2Login() - not configurable #91

Closed
fcbogle opened this issue Sep 30, 2018 · 18 comments

Comments

@fcbogle
Copy link

fcbogle commented Sep 30, 2018

Hello,
I am working with Spring Boot 2.0.5 and Okta 0.6.0.
I am following a tutorial https://github.com/okta/samples-java-spring/blob/master/okta-hosted-login/src/main/java/com/okta/spring/example/CodeFlowExampleApplication.java but cannot get beyond an issue related to the redirect URI and too many redirects.

The redirect to Okta works successfully, the problems begin on the redirect back to localhost.

The UI I receive from my application is here:
image

I have set the redirect URI for my OIDC App to localhost:8082/callback and this is the configuration of my yml file:
security:
oauth2:
client:
client-id: XXXX
client-secret: XXX
access-token-uri: https://dev-848116.oktapreview.com/oauth2/XXX/v1/token
user-authorization-uri: https://dev-848116.oktapreview.com/oauth2/XXX/v1/authorize
client-authentication-scheme: form
sso:
login-path: /callback

okta:
oauth2:
issuer: https://dev-848116.oktapreview.com/oauth2/XXX

The Security configuration I am using is here:
@configuration
@EnableOAuth2Sso
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {

/*public ApplicationSecurity(ApplicationContext applicationContext) {
    super(applicationContext);
}*/

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
      .antMatcher("/**")
      .authorizeRequests()
      .antMatchers("/callback")
      .permitAll()
      .anyRequest()
      .authenticated();
}

/*@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}*/

}
I have also tried the security configuration by extending the 'OAuth2SsoDefaultConfigurationclass however I can see this class implements theWebSecurityConfigurerAdapter` interface so perhaps no surprises it operates the same way.

It appears to me the http security is being ignored or bypassed. The controller config is very simple, here is the /callback implementation:

@GetMapping("/callback")
public String callback(OAuth2Authentication authentication, Model model) {
logger.info("Returning principal page: " + authentication.getUserAuthentication().getName());
model.addAttribute("user", authentication.getUserAuthentication().getName());
return "home";
}

Can you please advise what I need to do to resolve this, I'm not sure I need a concrete implementation of the /callback endpoint.

@fcbogle
Copy link
Author

fcbogle commented Sep 30, 2018

On inspection of the traffic between Okta and my localhost I see the following and perhaps significantly the Upgrade-Insecure-Requests: 1 and multiple of the redirects below:

HTTP/1.1 302
Redirect to: http://localhost:8082/callback
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
Location: http://localhost:8082/callback
Content-Length: 0
Date: Sun, 30 Sep 2018 19:16:16 GMT

GET http://localhost:8082/callback
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=EA2326C063782198417EA4DE2DC733A8

@fcbogle
Copy link
Author

fcbogle commented Oct 1, 2018

I double checked the pom versions and dependencies and aligned with my own project. Having done that I no longer have the redirect problem. However I get an NPE from the /callback controller method related to the authentication reference.

My last change was to the security config to follow the tutorial i.e to make use of OAuth2SsoDefaultConfiguration:

@configuration
@EnableOAuth2Sso
public class ApplicationSecurity extends OAuth2SsoDefaultConfiguration {

public ApplicationSecurity(ApplicationContext applicationContext) {
    super(applicationContext);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
      .antMatcher("/**")
      .authorizeRequests()
      .antMatchers("/callback")
      .permitAll()
      .anyRequest()
      .authenticated();
}

@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

}

When I start the service I get the following stacktrace:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceServerTokenServices' defined in class path resource [com/okta/spring/oauth/code/OktaOAuthCodeFlowConfiguration$LocalTokenValidationConfig.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class com.okta.spring.oauth.code.OktaOAuthCodeFlowConfiguration$Non500ErrorDefaultTokenServices: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:581) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.fcbogle.spring.SatsOauthClientApplication.main(SatsOauthClientApplication.java:12) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.0.5.RELEASE.jar:2.0.5.RELEASE]
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class com.okta.spring.oauth.code.OktaOAuthCodeFlowConfiguration$Non500ErrorDefaultTokenServices: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:208) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:473) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:355) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:304) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:431) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1703) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
... 20 common frames omitted
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_144]
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:337) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:58) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
... 27 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.GeneratedMethodAccessor27.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
... 40 common frames omitted
Caused by: java.lang.IllegalAccessError: class com.okta.spring.oauth.code.OktaOAuthCodeFlowConfiguration$Non500ErrorDefaultTokenServices$$EnhancerBySpringCGLIB$$464d78ac cannot access its superclass com.okta.spring.oauth.code.OktaOAuthCodeFlowConfiguration$Non500ErrorDefaultTokenServices
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_144]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_144]
... 45 common frames omitted

@fcbogle
Copy link
Author

fcbogle commented Oct 1, 2018

The application starts without devtools in the pom although I still have the redirect issue

@bdemers
Copy link
Contributor

bdemers commented Oct 1, 2018

Hey @fcbogle!

I'm guessing you have security.oauth2.sso.loginPath set to /callback?

Either way, you don't want to handle the callback directly, you would typically do this with a handler, take a look at the example in: spring-projects/spring-security#4472

@fcbogle
Copy link
Author

fcbogle commented Oct 1, 2018

Hi @bdemers many thanks for looking at my request!
Yes, the security.oauth2.sso.loginPath is set as you suggest to /callback
I'll take a look now at the handlers. Thanks, again.
Do you have any thoughts about the many redirects I am experiencing? I guess this could also be related to a lack of handler. Regards and Thanks

@bdemers
Copy link
Contributor

bdemers commented Oct 1, 2018

I'm guessing it is because of your @GetMapping("/callback") method. I've never tried to do that, but i'd start there. If you pull that out and still end up with the same issue let me know!

@fcbogle
Copy link
Author

fcbogle commented Oct 1, 2018

I'll do that and come back if the handler doesn't resolve the problems. Out of interest, how is the Authentication created behind the scenes? The AuthenticationSuccessHandler needs an Authentication object to do it's stuff. Is that created by the Okta starter or Spring? How should OI consider the management of GrantedAuthorites within the Okta configuration? Thank you

@bdemers
Copy link
Contributor

bdemers commented Oct 1, 2018

It's all handled by Spring Security directly. As far as GrantedAuthorties goes, are you trying to add them to the context or use them to protect your methods?

@fcbogle
Copy link
Author

fcbogle commented Oct 1, 2018

I was planning on differentiating between admin/regular users. Not much more than that. I guess I would add preAuthorization protection on some methods

@bdemers
Copy link
Contributor

bdemers commented Oct 1, 2018

Sure, but what is the source of the roles? accessToken claims? oauth scopes? or some external source? I can point you to examples for the first couple, and possibly the right direction for the last

@fcbogle
Copy link
Author

fcbogle commented Oct 1, 2018

Hi @bdemers I would probably use access token claims. Regarding an earlier update, in order to make use of:

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          //.antMatcher("/**")
          .authorizeRequests()
          .anyRequest()
          .authenticated()
          .and()
          .oauth2Login()
          .successHandler(new SsoAuthenticationSuccessHandler());
    }

I had to add:

<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-oauth2-client</artifactId>
</dependency>

to the pom.
I am now trying to reconfigure the yml file to follow these property values:
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-security-oauth2-client
I am now getting the following exception. I am not sure what maven dependencies I should be using so its almost guess work.

org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
	at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getRedirectForAuthorization(AuthorizationCodeAccessTokenProvider.java:359) ~[spring-security-oauth2-2.2.0.RELEASE.jar:na]
	at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:205) ~[spring-security-oauth2-2.2.0.RELEASE.jar:na]
	at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221) ~[spring-security-oauth2-2.2.0.RELEASE.jar:na]
	at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173) ~[spring-security-oauth2-2.2.0.RELEASE.jar:na]
	at org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:105) ~[spring-security-oauth2-2.2.0.RELEASE.jar:na]
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:128) ~[spring-security-oauth2-client-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]

Thank you for spending time looking at this and your advice.

@fcbogle
Copy link
Author

fcbogle commented Oct 2, 2018

Hi @bdemers I'm going to go back to the tutorial you published here: https://github.com/okta/samples-java-spring/blob/master/okta-hosted-login/src/main/java/com/okta/spring/example/CodeFlowExampleApplication.java
Can you please suggest how I should implement the authentication success handler in this scenario. The reason for asking is I'm not sure the .oauth2Login() WebSecurityConfigurerAdapter option is available from the maven dependencies i.e. without importing spring-security-oauth2-client. When I import spring-security-oauth2-client there seems to be a different yml configuration expected and I can't move forward with that currently. Thank you!

@bdemers
Copy link
Contributor

bdemers commented Oct 2, 2018

@fcbogle taking one step back for a sec Is there anything specific you want to do in your success handler? (I ask because there might even be an easier way via Spring Security)

@fcbogle
Copy link
Author

fcbogle commented Oct 2, 2018

Hi @bdemers nothing fancy, just redirect the user to an appropriate endpoint based on the claims within the access token. I'm trying to get a basic OAuth2 implementation running so I can break up a monolithic code base, thankfully already written in Java, to a more distributed and federated design. I will probably provide an access point to the resource servers via an OAuth2 Client application that can access services across a series of resource servers. Right now I want to identify the correct OAuth2 client design to use based on Okta, which will be responsible for primarily Authentication as well as some Authorisation based on the token claims. I would like to use the token claims as the basis to assigning Granted Authorities in the authentication success handler, much in the same way as the UserDetailsService.

@bdemers
Copy link
Contributor

bdemers commented Oct 2, 2018

This actually had me a bit stumped. I think the root of the issue is Spring Securities's oauth properties have changed between 4 and 5. The older properties (which we are using project) still work when you have the correct dependencies, but http.oauth2Login() doesn't (as you originally noted). I tried a bunch of work arounds with no success.

I'd recommend using Spring Security directly, see: https://developer.okta.com/blog/2017/12/18/spring-security-5-oidc

After that you can can configure the handler as expected, something like:

    @Configuration
    static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            // all requests
            http.authorizeRequests().anyRequest().authenticated();

            http.oauth2Login().successHandler((request, response, authentication) -> {
                log.info("Authorities are: {}", authentication.getAuthorities());
                // do something with the authorities
                response.sendRedirect("/");
            });
        }
    }

I've been pretty excited to update this project to the latest Spring Sec version (but that is still a couple weeks out)

@bdemers bdemers changed the title Too Many Redirections: Okta Spring Boot OAuth2 Client Spring Sec 5 /Boot 2 + custom WebSecurityConfigurerAdapter -http.oauth2Login() - not configurable Oct 2, 2018
@fcbogle
Copy link
Author

fcbogle commented Oct 3, 2018

Hi @bdemers once again thanks for your help on this work, greatly appreciated!
I have followed the link to the security 5 oidc tutorial and it working really well.
I notice in the link there is no need to use the @EnableAuth2Sso annotation and it got me thinking about integrating an OAuth2 client like this with one or more Resource servers. Can you please advise whether the yml file for a Resource Server needs to change and whether there is any advice about the use of Resource Servers that need to validate access_token assigned from am Okta Authorization Server - also local versus remote token validation - I have done this in the past using a public key, but not sure about how to configure that using Okta.
spring: thymeleaf: cache: false security: oauth2: client: registration: okta: client-id: {clientId} client-secret: {clientSecret} provider: okta: authorization-uri: https://{yourOktaDomain}/oauth2/default/v1/authorize token-uri: https://{yourOktaDomain}/oauth2/default/v1/token user-info-uri: https://{yourOktaDomain}/oauth2/default/v1/userinfo jwk-set-uri: https://{yourOktaDomain}/oauth2/default/v1/keys
Regards

@mraible
Copy link
Contributor

mraible commented Oct 3, 2018 via email

@bdemers bdemers added Analysis and removed Triaged labels Feb 25, 2019
@bdemers
Copy link
Contributor

bdemers commented Feb 28, 2019

As of 1.0+ you should be able to override the defaults. Please leave a comment if run into any trouble!

@bdemers bdemers closed this as completed Feb 28, 2019
@bdemers bdemers removed the Analysis label Feb 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants