Spring OAuth2 Authorization Server + Spring WebFlux - java

I'm trying to rewrite existing OAuth2 authorization service using Spring Boot 3.0.2 and newly released Spring OAuth2 Authorization Server 1.0.0.
Faced a trouble combing objects from Reactive Security and Standard Security libraries: unable to apply default security to OAuth2AuthorizationServerConfiguration class, because it's not applicable to reactive ServerHttpSecurity.
Code part
#Bean
#Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityWebFilterChain authServerSecurityFilterChain(ServerHttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http
.formLogin()
...;
return http.build();
}
Can't pass HttpSecurity to applyDefaultSecurity() method.
Tried to find any reactive implementations of OAuth2AuthorizationServerConfiguration class but found nothing.
Is there any way to convert ServerHttpSecurity to HttpSecurity? Or Spring OAuth2 Authorization Server is completely incompatible with reactive approach?
Main dependencies of Maven pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>1.0.0</version>
</dependency>
Thanks is advance.
UPD
Searched badly. Seems like it's not supported yet:
https://github.com/spring-projects/spring-authorization-server/issues/152
Or there are still some ways make it work?

Official answer:
We are strictly focusing on a Servlet implementation for the initial set of features that would qualify for a MVP version. We haven't decided whether we'll provide a WebFlux version at this point.
Quite honestly, I'm not convinced it's needed. The client and resource server(s) are the most active, whereas, the authorization server is not as active as it simply issues a token and may validate a token, which is limited activity between the many interactions that follow between a client and resource server after a token is issued.
Either way, I'm going to close this issue as WebFlux is not on the roadmap as of now.
Source - https://github.com/spring-projects/spring-authorization-server/issues/152

Related

Spring Boot custom SSL key-store loading logic

I'm using Spring boot 2.x and I need to configure the SSL on it.
To enable the SSL it's easy: just filling these properties:
server.port=443
server.ssl.keyStoreType=PKCS12
server.ssl.key-store=classpath:keystore/mycertificate.p12
server.ssl.key-store-password=mypassword
security.require-ssl=true
But I need this additional behaviour: Instead of loading the certificate from a specific path (server.ssl.key-store) I need to have a custom loading logic: I need to implement this custom way using, for example, the AWS Secrets service or similar.
So, is it possible? Is there a possibility to extend this default behaviour in Spring specifying a custom loader or something like this?
spring boot uses by default tomcat and tomcat can only be configured with the properties which you mentioned in your question. So it is not flexible and I think it is not possible to accomplish this with the default spring boot configuration with tomcat. I faced similar challenges and the solution I applied was to replace the embedded tomcat server with jetty. With Jetty it is possible to configure the ssl properties on runtime while getting it from for example your aws secrets service. See this project as an example: https://github.com/Hakky54/java-tutorials/tree/main/instant-server-ssl-reloading/server
So what I can recommend is to first exclude tomcat from your dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
Include Jetty server to spring boot:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
#Bean
public SslContextFactory.Server sslContextFactory() {
return fooService.createSslContextFactory();
}
#Bean
public ConfigurableServletWebServerFactory webServerFactory(SslContextFactory.Server sslContextFactory) {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
JettyServerCustomizer jettyServerCustomizer = server -> {
ServerConnector serverConnector = new ServerConnector(server, sslContextFactory);
serverConnector.setPort(8443);
server.setConnectors(new Connector[]{serverConnector});
};
factory.setServerCustomizers(Collections.singletonList(jettyServerCustomizer));
return factory;
}

Spring 5 Oauth2 - How to provide the check token URL in my Resource server?

I need some help..
I set up an AuthorizationServer using #EnableAuthorizationServer from Spring-security-oauth2 for grant type "client_credentials". Able to create, check tokens and everything good with this.
/oauth/token
/oauth/checkToken
Followed this sample for Authorization server
I have a separate project that has the REST APIs to be secured. I can't use #EnableResourceServer because that project uses Spring 5.2.8 and the spring-security-oauth2 2.5 is causing conflicts (because it uses 4.x Spring jars and excluding them is causing more issues) while deploying over Weblogic, so I am using this sample.
Now in this sample how do I just provide a Checktoken url. This sample wants a JWT json type of file but I dont have it. I just want to keep it simple and use the checktoken url of the authorization server I created, similar to how #EnableResourceServer works.(like provided here except without #EnableResourceServer)
Where do I provide that? Any immediate help appreciated.
Following your example for the ResourceServer, this works for me:
#EnableWebSecurity
public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Value("${security.oauth2.resource.tokenInfoUri}") String tokenInfoUri;
#Value("${security.oauth2.client.clientId}") String clientId;
#Value("${security.oauth2.client.clientSecret}") String clientSecret;
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.authorizeRequests((authorizeRequests) ->
authorizeRequests
.antMatchers(HttpMethod.GET, "/message/**").hasAuthority("SCOPE_message:read")
.antMatchers(HttpMethod.POST, "/message/**").hasAuthority("SCOPE_message:write")
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::opaqueToken);
// #formatter:on
}
#Bean
OpaqueTokenIntrospector opaqueTokenIntrospector() {
return new NimbusOpaqueTokenIntrospector(tokenInfoUri,clientId,clientSecret);
}
}
I used the following spring security dependencies:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>oauth2-oidc-sdk</artifactId>
<version>8.22</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
<version>5.3.4.RELEASE</version>
</dependency>
Put your checkToken-Uri, client and clientSecret into your application.properties.
I ended up using the JWT sample Spring had provided, which gets the JWT public keys for verification on the resource server.
Follow the auth and resource server provided in Spring source sample project.
Works good so far until we migrate to a better IDM solution

Which JWT + Spring Security configuration method is relevant right now?

At the moment I am developing an authorization server using spring security + OAUTH2 and JWT, but in the examples there are many different ways, some of them are deprecated.
Tell me, please, the most current?
When creating a project, I plug dependency the Cloud OAuth2, then a dependency appears in
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
I also customize the annotating #EnableAuthorizationServer
I use this method, tell me how relevant is it?
I saw other ways where it was necessary to register and configure filters, providers, etc., this is closer to me, but I don’t understand which option is the most relevant now.

Don't spring-boot-starter-web and spring-boot-starter-webflux work together?

When I start to learn the spring-webflux, I have the question about this component.
I built a simple project, using maven to manage it. I addded the dependencies related to spring-boot-starter-web and spring-boot-starter-webflux, like :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
But it doesn't work. When removing the spring-boot-starter-web dependency, it can work well.
As explained in the Spring Boot reference documentation section about the web environment, adding both web and webflux starters will configure a Spring MVC web application.
This is behaving like that, because many existing Spring Boot web applications (using MVC) will depend on the webflux starter to use the WebClient. Spring MVC partially support reactive return types, so this is an expected use case. The opposite isn't really true, since a reactive application is not really likely to use Spring MVC bits.
So using both web and webflux starters is supported, but it will configure a Spring MVC application. You can always force the Spring Boot application to be reactive with:
SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)
But it's still a good idea to clean up dependencies as it would be easy to use a blocking feature in your reactive web application.
I had a similar issue using spring-boot-starter-webflux and spring-data-geode causing
DEBUG [http-nio-8082-exec-2] org.sprin.web.servl.resou.ResourceHttpRequestHandler 454 handleRequest: Resource not found
It was resolved by changing the application type
#SpringBootApplication
public class Web {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Web.class);
app.setWebApplicationType(WebApplicationType.REACTIVE);
SpringApplication.run(Web.class, args);
}
}
The whole class looks like this
After setting the application type, if I don't then call the SpringApplication in a static way, I get this:

Authentication login with Swagger

I am using Swagger UI for interactive REST endpoints representation. However, Swagger UI can be accessed by everyone who knows its URL. Is there any standard way to restrict Swagger UI access with user login.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>LATEST</version>
</dependency>
No, that is outside of swagger's concern. You would just use your normal WebSecurityConfigurerAdapter to control permissions to the swagger-ui.html URL. Would also be pretty confusing if you used different ways of configuring security IMO.
Example
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/swagger-ui.html")
.access("hasRole('ROLE_ADMIN')");
}
}
But that's if you wan't to do security based on URLs, you could just as much do controller based security, and security on your services if they were involved but they aren't in this case. Security is very much application specific. I can't say do it this way, you might not even want to use Spring Security at all, and just do your own thing, it's just another framework to make your life easier, you could just as easily access the current logged in user in the view resolver for the swagger-ui.html view and throw an Unauthorised exception or something like that.

Categories

Resources