-
Notifications
You must be signed in to change notification settings - Fork 136
-
Notifications
You must be signed in to change notification settings - Fork 136
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
Okta Spring Boot starter doesn't work with GraalVM #192
Comments
I tried to switch to Spring Security's dependencies and configuration as a workaround. I replaced the Okta Spring Boot starter with: <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency> And I changed spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-133320.okta.com/oauth2/default I can run everything just fine with
I get an error on startup:
Any ideas @jgrandja? |
I tried using the <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder:full</builder>
<env>
<BP_BOOT_NATIVE_IMAGE>1</BP_BOOT_NATIVE_IMAGE>
<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
-Dspring.native.remove-yaml-support=true
-Dspring.spel.ignore=true
</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env>
</image>
</configuration>
</plugin> Unfortunately, the same error still happens. |
Hmmm, the paketobuildpacks/builder repo says it's ... that didn't work. Same error. I'll try upgrading to Spring Boot 2.4.0-M3 and a snapshot of spring-graalvm-native. Nope, can't get a snapshot of spring-graalvm-native, even after adding snapshot repos. <repository>
<id>spring-snapshots</id>
<name>Spring Snapshot Repository</name>
<url>http://repo.spring.io/snapshot</url>
</repository> Error is:
I tried to clone and build spring-graalvm-native, but that fails too:
Ha, ^^ fails because I was trying to build with Java 15. Trying Java 11 now... Java 11 worked! Now I have spring-graalvm-native snapshots installed locally. If this build/run doesn't work, I'll try building with Java 11... ... 1 hour later ... Spring Boot 2.4.0-M3 and spring-graalvm-native snapshots did not solve the problem. Neither did building with Java 11. I'm stumped. |
It seems I might need to pass in <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<env>
<BP_BOOT_NATIVE_IMAGE>1</BP_BOOT_NATIVE_IMAGE>
<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
-Dspring.native.remove-yaml-support=true
-Dspring.spel.ignore=true
--enable-https
</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env>
</image>
</configuration>
</plugin> And it got me a bit further! Now I get:
I'll try downgrading... Downgraded to Spring Boot 2.4.0-M2 and 0.8.0 of Spring's GraalVM support. I get the same error. Hmmmm... Remembering that Spring Security doesn't auto-configure a resource server, I tried adding a package com.okta.rest;
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;
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(request -> request.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt());
}
} And that resulted in:
To try and fix this, I added the following to
Nope. Now the error is:
Next, I tried removing This does not solve the problem. |
I'm not sure on the exact overlap between running graal native image directly or via the Spring plugin (i'm guessing they are similar). It's a much different use case though, and I remember pulling out my hair to get things working originally. |
It looks like this will be fixed in Spring GraalVM Native 0.9.0, which is scheduled for December 18, 2020. |
From https://twitter.com/sdeleuze/status/1338508916171427841:
|
I tried this again today with the Spring GraalVM Native v0.8.4 release. Here's the steps I used. Create a new Spring Boot app using HTTPie:
Then, add a package com.okta.rest.controller;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(@AuthenticationPrincipal Principal principal) {
return "Hello, " + principal.getName() + "!";
}
} Configure it to talk to Okta using the Okta CLI:
Select Web > Okta Spring Boot Starter. I configured the Spring Boot Maven plugin: <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_BOOT_NATIVE_IMAGE>1</BP_BOOT_NATIVE_IMAGE>
<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
--enable-all-security-services
</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env>
</image>
</configuration>
</plugin> I added the Spring GraalVM dependency: <dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-graalvm-native</artifactId>
<version>0.8.4</version>
</dependency> And built my application.
I got an error about it not being available in a repo, so I added milestone repos to my <repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories> Then I tried to build it again. It fails with a reasonable error.
Like before, I updated my configuration to avoid proxies: @SpringBootApplication(proxyBeanMethods = false)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
} Same error, so I tried
|
I tried switching to Spring Security's dependencies and configuration as a workaround: <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency> Change spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-133320.okta.com/oauth2/default Then, I tried:
It worked! Next, let's see if it works:
Nope!
I updated my <env>
<BP_BOOT_NATIVE_IMAGE>1</BP_BOOT_NATIVE_IMAGE>
<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
--enable-all-security-services
--enable-url-protocols=https
</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env> Now it builds and runs! 💥 I tested it and it almost works.
This results in a 500:
In the Docker console, the error is:
|
Hmmm, the @bdemers Any idea why |
Changing my
After I got that fixed, I re-built the image:
Ran it in Docker:
Then, in another terminal window:
It works! 🎉 |
Next, I tried changing It built a few seconds faster: And it works, too! 💥 |
Good news 👍🏼 For the error you see with Okta, I think you need to refactor |
@arvindkrishnakumar-okta Any updates on this? I'd love for it to be possible to build native images for Spring Boot apps that use our starter. |
I tried this again today with Spring Boot 2.5.1, Spring Native v0.10.0, and the Okta Spring Boot starter v2.0.1. I don't expect a response from anyone on this, I just want to document the latest state of things. 🙂 Here's my pom.xml: <?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.5.1</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>11</java.version>
<spring-native.version>0.10.0</spring-native.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>${spring-native.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
--enable-all-security-services
--enable-url-protocols=https
</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env>
</image>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>${spring-native.version}</version>
<executions>
<execution>
<id>test-generate</id>
<goals>
<goal>test-generate</goal>
</goals>
</execution>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project> I added the following to my okta.oauth2.issuer=https://dev-1309757.okta.com/oauth2/default When I build with
Next, I replaced the Okta Spring Boot starter with Spring Security: <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency> And changed my property name in I also added a resource server with Spring Security. 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;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(request -> request.anyRequest().authenticated())
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
}
} Then, I built my image:
And ran it with:
Everything starts up:
And a call to
|
@mraible, the solution outlined by you above works for authentication, but not for authorization via the annotation @PreAuthorize("hasAuthority('<>')"). The behavior seems to be different when using the Okta Spring Boot Starter versus when using the spring-security-oauth2-resource-server. The same @PreAuthorize annotation works fine with Okta Spring Boot Starter, but gives a 403 with spring-security-oauth2-resource-server, the JWT access token being the same in both cases (it contains the proper "groups" attributes that I am trying to authorize against in the @PreAuthorize annotations). Do you have a suggestion on how to address this? Note: @PreAuthorize usage is as prescribed in this blog post: https://developer.okta.com/blog/2019/06/20/spring-preauthorize |
@mraible, I was able to solve the above issue with the @PreAuthorize("hasAuthority('<>')") that came up when I switched from okta-spring-boot-starter to spring-security-oauth2-resource-server per your outline (in order to get my Okta-driven Spring Boot app to compile and work with Spring Native). The root cause seems to be that the spring-security-oauth2-resource-server converts the JWT access token differently than okta-spring-boot-starter. It was not extracting the claims in the "groups" attribute of the access token JWT. By default, it extracts the "scope" attributes for authorities, which was not matching with my "@PreAuthorize("hasAuthority('<>')") annotations, where I had used the "groups" values that I had configured for the claims in my Okta config. This was resulting in the 403. To solve this, I added a custom JwtAuthenticationConverter as suggested in this post: https://stackoverflow.com/questions/58205510/spring-security-mapping-oauth2-claims-with-roles-to-secure-resource-server-endp. This allowed me to customize the JWT conversion logic in spring-security-oauth2-resource-server to use the "groups" attribute in the Okta JWT token to extract the claims. With this change, my "@PreAuthorize("hasAuthority('<>')") annotations now work correctly in the Spring Native build of my Okta Spring Boot app. So, I think the instructions you have outlined, along with the above additional step should together work well to get a Spring Boot app that uses Okta to build successfully with Spring Native and function correctly with the expected authn and authz behavior. |
@psinghal04 Your experience matches mine. When using Spring Security's resource-server in JHipster, we had to add a For |
This will be fixed by v2.1.1. |
Steps to reproduce:
Create a new Spring Boot app using HTTPie:
Then, add a
HelloController
:Configure it to be an OAuth 2.0 resource server by adding an issuer to
application.properties
:All the following should work at this point (I got an access token from oidcdebugger.com):
To add "build native image support", I followed these docs.
I upgraded my app to use Spring Boot v2.4.0-M2.
I updated my configuration to avoid proxies:
I added the milestone repos to my
pom.xml
:I configured the Spring Boot Maven plugin:
I added the Spring GraalVM dependency:
And built my application.
Then I tried to run it.
It fails with the following error:
The text was updated successfully, but these errors were encountered: