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
}
}
It gives me the following errors which I don't understand why I'm getting since I'm following the documentation :
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 :
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