0

I asked a question not long ago to know how to validate jwt token using spring boot and copied the dependencies on the sample here but updated them for the latest ones.

This is my build.gradle :

import org.apache.tools.ant.filters.ReplaceTokens

plugins {
    id 'org.springframework.boot' version '2.4.5'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'org.jetbrains.kotlin.jvm' version '1.4.32'
    id 'org.jetbrains.kotlin.plugin.spring' version '1.4.32'
    id "org.jetbrains.kotlin.plugin.jpa" version "1.4.32"
}

apply plugin: 'io.spring.dependency-management'
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'kotlin-jpa'

group = 'com.backend-project'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {

    def appInsightsVersion = '2.6.2'

    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-websocket'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
    implementation 'com.microsoft.sqlserver:mssql-jdbc:6.2.1.jre8'
    implementation 'com.h2database:h2:1.4.199'
    implementation 'io.springfox:springfox-swagger2:2.9.2'
    implementation 'io.springfox:springfox-swagger-ui:2.9.2'
    implementation 'org.jetbrains.kotlin:kotlin-reflect'
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
    implementation 'org.hibernate:hibernate-core'
    implementation 'javax.xml.bind:jaxb-api'
    implementation group: 'com.microsoft.azure', name: 'applicationinsights-web', version: appInsightsVersion
    implementation group: 'com.microsoft.azure', name: 'applicationinsights-logging-logback', version: appInsightsVersion
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    implementation 'org.springframework.boot:spring-boot-starter-validation:2.4.5'
    implementation 'org.springframework.boot:spring-boot-starter-security:2.4.5'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.4.5'
    implementation 'org.springframework.security:spring-security-oauth2-jose:5.3.9.RELEASE'
    compile 'org.springframework.security:spring-security-oauth2-core:5.3.9.RELEASE'

    compile 'io.jsonwebtoken:jjwt-api:0.11.2'
    runtime 'io.jsonwebtoken:jjwt-impl:0.11.2',
            'io.jsonwebtoken:jjwt-jackson:0.11.2'
    compile 'joda-time:joda-time:2.10.10'
    implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.68'


}

compileKotlin {
    kotlinOptions {
        freeCompilerArgs = ['-Xjsr305=strict']
        jvmTarget = '1.8'
    }
}

compileTestKotlin {
    kotlinOptions {
        freeCompilerArgs = ['-Xjsr305=strict']
        jvmTarget = '1.8'
    }
}


task copyWebConfig(type: Copy) {
    from("$rootDir/src/main/templates") {
        include 'web.config'
    }
    into "$buildDir/libs"
    filter(ReplaceTokens, tokens: [VERSION: project.version])
    inputs.property("VERSION", project.version)
    filter(ReplaceTokens, tokens: [PACKAGE_NAME: project.name])
    inputs.property("PACKAGE_NAME", project.name)

}

task copyLogBack(type: Copy) {
    from("$rootDir") {
        include 'logback-spring.xml'
    }
    into "$buildDir/libs"
}

assemble.dependsOn(copyWebConfig)
assemble.dependsOn(copyLogBack)

this is my web security implementation :

package com.renaulttrucks.transfertprotocolbackend.security.config

import com.renaulttrucks.transfertprotocolbackend.api.config.Router
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
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.http.SessionCreationPolicy
import org.springframework.security.oauth2.jwt.JwtDecoder
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
import org.springframework.util.ResourceUtils
import java.io.FileInputStream
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.security.interfaces.RSAPublicKey

@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {

    @Value("\${security.enabled}")
    val securityEnabled : Boolean? = false

    @Value("\${jwt.key-path}")
    var keyPath: String? = null

    var publicKey: RSAPublicKey? = null

    override fun configure(http: HttpSecurity) {

        if(!securityEnabled!!) {
            http.httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .and()
                .csrf().disable()
                .formLogin().disable()
        } else {
            http
                .authorizeRequests()
                .antMatchers("/api/companies/**").permitAll()
                .antMatchers(Router.API_PATH + "/**").authenticated()
                .and()
                .httpBasic()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .anonymous()
                .and()
                .securityContext()
                .and()
                .headers().disable()
                .rememberMe().disable()
                .requestCache().disable()
                .csrf().disable()
                .x509().disable()
                .httpBasic().disable()
                .formLogin().disable()
                .logout().disable()
                .oauth2ResourceServer(oauth2 -> oauth2
                    .jwt(jwt -> jwt.decoder(jwtDecoder()))
                )
        }
    }

    @Bean
    fun jwtDecoder(): JwtDecoder? {
        return NimbusJwtDecoder.withPublicKey(getPublicKeyFromString()).build()
    }

    fun getPublicKeyFromString(): RSAPublicKey? {
        if (this.publicKey != null) {
            return this.publicKey
        }
        val fin = FileInputStream(ResourceUtils.getFile(keyPath!!))
        val f: CertificateFactory = CertificateFactory.getInstance("X.509")
        val certificate: X509Certificate = f.generateCertificate(fin) as X509Certificate
        publicKey = certificate.getPublicKey() as RSAPublicKey?
        return publicKey
    }

}

The error happens here : enter image description here

It gives me the following errors which I don't understand why I'm getting since I'm following the documentation : enter image description here

Even when trying the kotlin dsl version like here by changing my configure function like bellow :

    override fun configure(http: HttpSecurity) {
        http {
            authorizeRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2ResourceServer {
                jwt {
                    jwtDecoder = jwtDecoder()
                }
            }
        }
    }

it gives me the following errors : enter image description here The first line's this : : Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public operator fun <T, R> DeepRecursiveFunction<TypeVariable(T), TypeVariable(R)>.invoke(value: TypeVariable(T)): TypeVariable(R) defined in kotlin

Running gradlew dependencyInsight --dependency org.springframework.security:spring-security-config - -configuration runtimeClasspath gives me this :

Welcome to Gradle 7.0!

Here are the highlights of this release:
 - File system watching enabled by default
 - Support for running with and building Java 16 projects
 - Native support for Apple Silicon processors
 - Dependency catalog feature preview

For more details see https://docs.gradle.org/7.0/release-notes.html

Starting a Gradle Daemon, 1 busy and 2 incompatible Daemons could not be reused, use --status for details

> Evaluating settings

> Task :dependencyInsight
org.springframework.security:spring-security-config:5.4.6 (selected by rule)
   variant "runtime" [
      org.gradle.status                  = release (not requested)
      org.gradle.usage                   = java-runtime
      org.gradle.libraryelements         = jar
      org.gradle.category                = library

      Requested attributes not found in the selected variant:
         org.gradle.dependency.bundling     = external
         org.gradle.jvm.environment         = standard-jvm
         org.jetbrains.kotlin.platform.type = jvm
         org.gradle.jvm.version             = 8
   ]

org.springframework.security:spring-security-config:5.4.6
+--- org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.4.5
|    \--- runtimeClasspath
\--- org.springframework.boot:spring-boot-starter-security:2.4.5
     \--- runtimeClasspath

(*) - dependencies omitted (listed previously)

A web-based, searchable dependency report is available by adding the --scan option.

BUILD SUCCESSFUL in 21s
1 actionable task: 1 executed

  • A good starting point is to make sure you are using the version of Spring Security that you are expecting. Try running `./gradlew dependencyInsight --dependency org.springframework.security:spring-security-config --configuration runtimeClasspath` to see if another dependency is overriding it. – Eleftheria Stein-Kousathana May 14 '21 at 10:29
  • @EleftheriaStein-Kousathana I've run the command and edited my question with the result, it seems like there is only one version of `spring-security-config` which is 5.4.6 – Hadestructhor May 14 '21 at 11:13
  • Try using the equivalent non-lambda configuration `oauth2ResourceServer().jwt().decoder(jwtDecoder())` to see if it changes anything. I also noticed that you are using Gradle 7. The Spring team uses Gradle 6 and there may be some features that are incompatible with Gradle 7. Try using Gradle 6.8.3 and see if it helps. – Eleftheria Stein-Kousathana May 14 '21 at 11:21
  • It seems like that works but now I'm having problems with the JUnit Test classes, I haven't modified them at all, it just seems like it can't find the annotations, should I add dependencies to them in my gradle build ? I didn't have any problems running my project before adding the security config and dependencies. Also changed my gradle version and it seems fine even when I didn't change it. – Hadestructhor May 14 '21 at 11:39
  • Nevermind my previous comment, mistake of mine from when I updated the spring boot version and forgot to do the same with the test class. The project now builds and runs without any errors. Thanks a lot for the help. – Hadestructhor May 14 '21 at 11:56

1 Answers1

0

Using the lambda version solved the issue as user Eleftheria Stein-Kousathana suggested :

oauth2ResourceServer().jwt().decoder(jwtDecoder())