How to verify jwt token in spring boot? - 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

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 ?

SpringBoot e2e tests using keycloak-spring-boot-starter

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

Using Keycloak 4.3.0.Final with dropwizard 1.3.1

I am having a problem with integrating keycloak into dropwizard. Keycloak requires the RestEasy client so i had to use the dependency :
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.26.Final</version>
</dependency>
then I create my httpClient :
RxClient<RxCompletionStageInvoker> httpClient = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration())
.buildRx(getName(), RxCompletionStageInvoker.class);
then i try to use the client, for example :
httpClient
.target(path)
.request()
.get();
and i get the error:
java.lang.ClassCastException: org.jboss.resteasy.client.jaxrs.internal.ClientRequestContextImpl cannot be cast to org.glassfish.jersey.client.ClientRequest
when i remove the dependency I get the JercyClient and all httpRequests works find but Keycloak builder fails, when I use RestEasy dependency keyCloak succeeds but all other http requests fails
Have anyone faced this problem before? is there a way to control when to get the resteasy client and when to get the jersey client?
The solution was to use RestEasy dependency but not using the JersyClientBuilder:
Client httpClient = new ResteasyClientBuilder().build();

Spring basic security confiugred userid/password not working

Our application is based on Spring-boot 2.0. I've enabled basic security by adding the following dependency to pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
I also have added properties so that I can define my own userid and password for basic security, instead of the generated ones. I defined them like this in /resources/applicaiton.properties file:
security.user.name=user1
security.user.password=pass1
When I startup my application, I can see that is still generates the password for me in the log. Also, I am unable to login using user1/pass1 combination. I can only successfully login with the user=user and password=generated-password-from-log file.
Why won't spring security allow me to login with user1/pass1? What could be the problem?
Those properties need the spring prefix.
spring.security.user.name=user # Default user name.
spring.security.user.password= # Password for the default user name.
If I want to configure something I often take a look at this List
I hope this helps.

Spring-Social-facebook + Spring MVC integration

I am trying to access facebook data via spring social facebook integration using the instructions provided at http://spring.io/guides/gs/accessing-facebook.
But currently i am facing 2 type of problem
When i run example as mentioned in tutorial i get following error
No matching bean of type [org.springframework.social.facebook.api.Facebook] found for dependency
When i run this with #Configuration on FacebookConfig class, i get below mentioned error
A ConnectionFactory for provider 'facebook' has already been registered
Is there a workaround to it?
I have kept the war file with source code at https://skydrive.live.com/redir?resid=EA49CD7184E0E40!168&authkey=!AIkoKKx5-Um8AQE
What version are you using?
Try using the version 1.1.0.RELEASE
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-facebook</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
If it not works, please try post the stacktrace printed.
You need to create a the beans to your class, please post more information like your pom.xml and your spring context configuration.
Ihad the same problem. Spring Social Facebook will automatically add connection factory based on the configuration in application.properties. This auto-configured connection factory is clashing with the one that you're trying to add. Try just to remove your connection factory you add through addConnectionFactories.
Try to use different setting to load your custom connection factory...
E.g. Instead of using OOTB keys use different keys:
#Facebook Social App Details:
# Commented below 2 OOTB Keys & Bingo it worked.
#spring.social.facebook.appId=APP_ID
#spring.social.facebook.appSecret=APP_SECRET
facebook.app.id=APP_ID
facebook.app.secret=APP_SECRET
This will resolve your problem.

Resources