Search code examples
spring-securityoauth-2.0jwtspring-cloud

Protecting the service using OAuth2, JWT token not working Spring cloud


I have a micro service architecture. And I am securing the service by using OAuth2 and configured in using the JWT token. I am having a problem regarding securing the services in this micro service. I have implemented the authorization server successfully. I am able to generate the JWT token and access the protected resource of Authorization server.

For securing the micro sevices I have done the following things:

  1. Added dependency in pom file of the micro service that i want to secure with OAuth2:
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
  1. Modified the boostrap application as below:
@SpringBootApplication
@EnableResourceServer
public class Application {

            ...
}
  1. Created the JwtTokenConfiguration as below:
    private String getPublicKeyAsString() {

        try {
            Resource resource = new ClassPathResource("publickey.pem");
//          return IOUtils.toString(oAuth2ConfigProperties.getJwt().getPublicKey().getInputStream(),
//                  StandardCharsets.UTF_8);
            String strPublicKey= ".....";
            String verifierKey = String.format("-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----", strPublicKey);
                  //verifierKey = String.format("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", strPublicKey);

            System.out.println(verifierKey);
            return verifierKey;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setVerifierKey(getPublicKeyAsString());
        return jwtAccessTokenConverter;
    }

The error is like below:

    ... 33 common frames omitted
Caused by: java.lang.IllegalStateException: For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key
    at org.springframework.util.Assert.state(Assert.java:73) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter.afterPropertiesSet(JwtAccessTokenConverter.java:318) ~[spring-security-oauth2-2.3.4.RELEASE.jar:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    ... 53 common frames omitted

The oauthcer.jks is located in the authorization server. I have generate the public from the oauthcer.jks by running the commmand below:

keytool -list -rfc --keystore oauth2cer.jks

The result that i get from running command is like below:

-----BEGIN CERTIFICATE-----
MIIDfDCCAmSgAwIBAgIJAM8UC/xKlIfwMA0GCSqG ...
-----END CERTIFICATE-----

I tested the result in the url : https://8gwifi.org/PemParserFunctions.jsp and it works fine.

I don't know why it is not working. I have tried many things. I will apriciate any guide.


Solution

  • I have faced a similar problem. What you are doing wrong is you are passing the certificate to the: jwtAccessTokenConverter.setVerifierKey(getPublicKeyAsString());. You need to pass the public key.

    To fix this issue you need to extract the public key from the oauth2cer.jks. Execute the command below to extract the public key:

    keytool -list -rfc --keystore oauth2cer.jks | openssl x509 -inform pem -pubkey -noout
    

    After executing the command above it will display the result like below:

    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAdfsdfsdaxzcCAQ8AMIIBCgKCAQEAvJXQdLvlF1d
    hx+AAzmNpuD89XPFAcmrvCt7CTGzi0bd/3WzK8dP2clxnVFANh7mbu24U91jK9ZS
    3rewr4534tgfdryt54ytry6uyr
    -----END PUBLIC KEY-----
    

    The result above needs to be passed to the setVerifierKey method.