SpringBoot e2e tests using keycloak-spring-boot-starter - spring-boot

My SpringBoot application has following keycloak dependency to connect to the Keycloak server. I used this tutorial for the setup.
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
The application works fine, the problem is however with e2e Tests. I use following code for e2e tests
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
class ServerIntegrationTests {
#Autowired
TestRestTemplate restTemplate;
// ...
}
For authorization-server mocking I use following lib:
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-keycloak</artifactId>
<version>${springaddons.version}</version>
<scope>test</scope>
</dependency>
This lib however seems to work only with #MockMvc, but not with real HTTP-Calls, i.e. #TestRestTemplate.
So my questions are:
Does com.c4-soft.springaddons only support #MockMvc context?
If so, what are the other possibilities to test whole application (without mocking servlet container) with mocked authorization-server (keycloak)?
I have tried following lib, but it does not work with keycloak-spring-boot-starter:
<dependency>
<groupId>no.nav.security</groupId>
<artifactId>mock-oauth2-server</artifactId>
<version>0.5.1</version>
<scope>test</scope>
</dependency>

Does com.c4-soft.springaddons only support #MockMvc context?
No it works without MockMvc. It supports WebTestClient too or just testing secured #Component outside of any HTTP request (#Repository and #Service for instance).
But its usage is limited to unit-testing only. Here is why
I'm not sure you can mock authorization-server: spring-security validates the JWT bearer against its issuer and for that the token must be valid and signing key accessible from configured issuer (unless you modify security filters, but then your test wont cover production security anymore).
You might have to use a dockerised Keycloak or something. After all, aren't you writing end-to-end test for a system which includes an authorization-server?
Your tests will first issue a POST request to Keycloak to be delivered a valid access-token and then add it as authorization header to the test requests sent to your resource-server(s).
P.S.
keycloak-spring-boot-starter is deprecated: https://github.com/keycloak/keycloak/discussions/10187
You can have a look at those tutorials for an alternative

Related

Why does OAuth2AuthorizedClientService requires spring-boot-starter-web to autowire?

I am trying to write an OAuth2 Client SpringBoot app that :
Does NOT require a web container ( no Tomcat nor Jetty ) ...
To basically send an Authorization bearer header ( either opaque or JWT bearer token ) in an HTTP request to another SpringBoot app that acts an OAuth2 resource server.
Now looking at the documentation here :
https://docs.spring.io/spring-security/reference/5.7/servlet/oauth2/client/core.html#oauth2Client-client-registration-repo
.. it says that both OAuth2AuthorizedClientService and ClientRegistrationRepository should be auto-wired automatically:
#Autowired
private OAuth2AuthorizedClientService oAuth2AuthorizedClientService;
#Autowired
private ClientRegistrationRepository clientRegistrationRepository;
presumably by just having :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
But it turns out that I also need :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
for the auto-wiring to work. Otherwise, I get :
Field oAuth2AuthorizedClientService in org.example.oauth2client.FeignConfiguration required a bean of type 'org.springframework.security.oauth2.client.OAuth2AuthorizedClientService' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.springframework.security.oauth2.client.OAuth2AuthorizedClientService' in your configuration.
So question is, why is spring-boot-starter-web needed to have the auto-wiring to work ?
I don't want to add a web container as the OAuth2 client SpringBoot app does not require it ( e.g. command-line app ) but needs to consume a REST service from another SpringBoot app running as an OAuth2 resource server.
OK ... I found the answer, though not what I was expecting.
DefaultOAuth2AuthorizedClientManager is asserting and expecting a HttpServletRequest:
https://github.com/spring-projects/spring-security/blob/5.7.x/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManager.java#L144
So the spring security's OAuth2 client only works in the context of where the client app is running in a web server container.
It looks like I then cannot use spring-boot-starter-oauth2-client for apps that are not running in a web server container. ( e.g. command line or batch application ), but why ???
In this case, what options do we have ?

How to verify jwt token in spring boot?

I want to implement JWT verification in my spring boot application. The algorithm we used for signing token is Ed25519\EDDSA .
I don't find right dependency/library to implement Jwt verifier using ED25519 algorithm.
Can someone suggest maven dependency to validate JWT token ?
The answer comes late but I just tried to solve the same problem and decided to share my conclusions.
I'd use Spring Security with the OAuth 2.0 Resource Server to validate JWTs.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
However, Spring Security's default JWT Decoder NimbusJwtDecoder does not support EdDSA (see list of supported signature algorithms. You will have to write your own JWTDecoder.
Luckily, Spring Security depends on Nimbus JOSE+JWT library that already supports EdDSA. To validate an EdDSA signature with the library, add the following dependency:
<dependency>
<groupId>com.google.crypto.tink</groupId>
<artifactId>tink</artifactId>
<version>1.6.1</version>
</dependency>
Your code will at some point call the following lines, where encodedJwt is the encoded jwt string.
SignedJWT signedJWT = SignedJWT.parse(encodedJwt);
JWSVerifier verifier = new Ed25519Verifier(publicJWK);
assertTrue(signedJWT.verify(verifier));
The complete example can be found here: https://connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-eddsa

How to get access to the Spring-boot actuator JSON payload

I m working on a customized health check for an API. Where I m using :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.5.5</version>
</dependency>
and implementing the HealthIndicator interface.
I m wondering if there is a way to get access to the payload returned by /actuator/health ?
so I can desterilize it, and base on the values on the object (payload), I will build the implementation for the heath() method from HealthIndicator Interface.
I have tried to use:
- HealthEndpoint but it needs an implementation for HealtContributorRegistary , not sure how to do that.
- SystemHealth (im getting the error : class Cannot be accessed from outside package).
any help is very welcomed.
Thank you.
I was able to get access to all my API components status by
#Autowired HealthContributor[] healthContributors;
in a service.
I have followed this answer : Direct access to Spring Boot Actuator Health beans/data?

How to use OpenApi annotations in spring-webflux RouterFunction endpoints?

I am currently working on a project where I use spring functional web programming. I usually use annotations of swagger 2 in restController but with functional web programming I can not find where ! The place to tell the app to do a search for endpoints (like basepackage in Docket) and load swagger in an html page.
Here is my code:
#Configuration
public class RouterClient{
#Bean
public RouterFunction<ServerResponse> routes(ClientHandler client){
return route(GET("/api/client"), client::findAll)
.andRoute(POST("/api/client"),client::add);
}
}
Config Class:
#Configuration
public class OpenApiConfiguration{
#Bean
public GroupedOpenApi groupOpenApi() {
String paths[] = {"/api/**"};
String packagesToscan[] = {"com.demo.client"};
return GroupedOpenApi.builder().setGroup("groups").pathsToMatch(paths).packagesToScan(packagesToscan)
.build();
}
}
The dependencies:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-core</artifactId>
<version>1.2.32</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId>
<version>1.2.32</version>
</dependency>
The result :
Functional endpoints are supported since 1.3.8 (early May). See releases on GitHub.
Have a look at this: https://springdoc.org/#spring-webfluxwebmvc-fn-with-functional-endpoints
The easiest way to see your endpoints on the Swagger UI is to add the #RouterOperation annotation to your RouterFunction methods (containing a single route), and specify the beanClass and beanMethod used in it. However, in your case, there are multiple routes on a single method, so you must also use the #RouterOperations annotation. These cases are well documented in the link above.
It seems like the current implementation of springdoc-openapi only allows to manually add the documentation.
set
springdoc.api-docs.enabled=false
This will skip classpath scanning (springfox) for the API annotations. (OAS3 replaced these in v3) and replace them with reading in the spec file (json/yaml).
Put the documentation in the Spec files, as one can generate any number of clients from these. Easiest way to start with legacy code is to copy the /api-docs/ files generated by springfox.
You can go to editor.swagger.io, load in the version 2 yaml and convert it to version 3 if springfox still doesn't do that. Then work with yaml files. (it's a contract UP-Front specification for a reason)
https://springdoc.org/
You need springdoc-openapi-webflux-ui and #RouterOperation.
spring-webflux with Functional Endpoints, will be available in the future release

Expose metrics from spring application to prometheus without using spring-boot actuator

I have been trying to collect micrometer metrics in a non springboot application and expose them to prometheus.I have added the following dependency and the test method for the same.I would like to know how to proceed and expose the collected metrics to prometheus from my non spring boot application(traditional spring application).
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.2.0</version>
</dependency>
public string testmetrics(){
private PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
registry.counter("ws metric collection","tktdoc metrics");
String metricsInfo = registry.scrape();
return metricsInfo;
}
You practically have to expose an HTTP endpoint and configure Prometheus with it; the HTTP endpoint will supply the data for the scrapes.
An example showing how to add the HTTP endpoint by starting up an HTTP Server (your application may already be using one) is here.

Resources