okta/okta-spring-boot

Groups no longer converted to Authorities with Version 1.5.0

stephanabel opened this issue · 10 comments

Hi there,

previous to version 1.5.0 (we had 1.4.0) the group claims where automatically converted to org.springframework.security.core.GrantedAuthority's.

This functionality seems to be provided by com.okta.spring.boot.oauth.OktaJwtAuthenticationConverter, which is used in version 1.4.0. In the latest version the class is still there but seemingly no longer used (instead org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter is used in my case).

The Spring Security Configuration in my case is the following:

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers("/actuator/**", "/swagger-ui/**", "/v3/api-docs").permitAll()
        .and()
        .authorizeRequests().anyRequest().authenticated()
        .and().oauth2ResourceServer().jwt();
  }
}

Could you take a look at this? Am i missing something?
Please let me know if you need any additional information.

@stephanabel Thanks for posting!

With v1.5.0 we upgraded to Springboot v2.4.0. This recent Spring upgrade (Spring Security v5.4.0) allows you to define the JwtAuthenticationConverter as a @bean configuration (See section named OAuth 2.0 Resource Server at https://docs.spring.io/spring-security/site/docs/5.4.0/reference/html5/#new). In our Springboot SDK, you can see this bean defined here. This bean should take care of converting the group claims. So, you no longer need to set the jwt converter explicitly in your WebSecurityConfig.

Let me know if you need more info.

Hey @stephanabel!

I'd like to try to reproduce this, do you have any other configuration/beans set?

Also, which version of Spring Boot are you using? Make sure you are using 2.4+

Hey @bdemers & @arvindkrishnakumar-okta, thanks for your reply!

So i assume this bean definition in com.okta.spring.boot.oauth.OktaOAuth2AutoConfig:

  @Bean
  public JwtAuthenticationConverter jwtAuthenticationConverter(OktaOAuth2Properties oktaOAuth2Properties) {
    OktaJwtAuthenticationConverter converter = new OktaJwtAuthenticationConverter(oktaOAuth2Properties.getGroupsClaim());
    converter.setJwtGrantedAuthoritiesConverter(new JwtGrantedAuthoritiesConverter());
    return converter;
  }

should now be used by default trough the starter.
Unfortunately this is not the case for me.

I saw that @bdemers provided a okta-spring-boot-migration-demo (https://github.com/bdemers/okta-spring-boot-migration-demo) project for another issue. I used the project to reproduce the problem.

Update Spring-Boot to 2.4.0 and Okta Starter to 1.5.0:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.okta.spring</groupId>
			<artifactId>okta-spring-boot-starter</artifactId>
			<version>1.5.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Set the following properties (since we use a custom AuthServer with a different audience):

okta.oauth2.issuer=https://<ourdomain>/oauth2/<ourauthserver>
okta.oauth2.audience=api://<notdefault>

I then used Postman to call the endpoint of the demo application with an jwt that contains groups.

The Result of the call are authorities not including the Groups.
I also set up break points in com.okta.spring.boot.oauth.OktaJwtAuthenticationConverter#extractAuthorities to see if the method is called. In the Okta-Starter with Version 1.5.0 it is not called. in Version 1.4.0 it is called.

If you need any additional information please let me know.

Hi there,

i have figured out why the bean was never present in my configuration. Ich checked the condition evaluation for com.okta.spring.boot.oauth.OktaOAuth2AutoConfig and found one unmatched condition:

"OktaOAuth2AutoConfig": {
                    "notMatched": [
                        {
                            "condition": "OnPropertyCondition",
                            "message": "@ConditionalOnProperty (spring.security.oauth2.client.registration.okta.client-id) did not find property 'spring.security.oauth2.client.registration.okta.client-id'"
                        }
                    ],
                    "matched": [
                        {
                            "condition": "OnClassCondition",
                            "message": "@ConditionalOnClass found required classes 'org.springframework.security.config.annotation.web.configuration.EnableWebSecurity', 'org.springframework.security.oauth2.client.registration.ClientRegistration'"
                        },
                        {
                            "condition": "OnWebApplicationCondition",
                            "message": "found 'session' scope"
                        }
                    ]
                },

If I provide a dummy property for the missing property (spring.security.oauth2.client.registration.okta.client-id="test") the Config is loaded, the bean is present and the groups are getting converted to Authorities.

@stephanabel Great find/debugging, and the suggested workaround is good too.
I think I have a fix, and I'll push a PR in a few minutes

@stephanabel your debugging made this super easy to find/fix, see #220 if interested

Thanks again!

Thanks @stephanabel & @bdemers. I've merged #220. Will release a patch version 1.5.1 shortly.

Released 1.5.1 with this fix.

Thanks @bdemers & @arvindkrishnakumar-okta for the quick fix!