split jwt issuer and verifier (#40)

This commit is contained in:
Alexander Buntakov 2021-08-02 16:06:42 +03:00 committed by GitHub
parent e9a8c86515
commit a95b1ac4fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 34 deletions

View File

@ -6,6 +6,7 @@ plugins {
dependencies {
implementation(project(":auth-core"))
implementation(project(":auth-jwt"))
implementation("com.auth0:java-jwt")
implementation("org.springframework.security:spring-security-oauth2-jose")

View File

@ -1,35 +1,33 @@
package ru.touchin.auth.core.tokens.access.config
import com.auth0.jwt.algorithms.Algorithm
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import ru.touchin.auth.core.tokens.access.properties.AccessTokenProperties
import ru.touchin.common.string.StringUtils.emptyString
import ru.touchin.auth.security.jwt.configurations.JwtConfiguration
import ru.touchin.auth.security.jwt.utils.JwtUtils.getKeySpec
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey
import java.security.interfaces.RSAPublicKey
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
import java.util.*
@Configuration
@Import(JwtConfiguration::class)
class AccessTokenBeanConfig(private val accessTokenProperties: AccessTokenProperties) {
@Bean
fun accessTokenSigningAlgorithm(): Algorithm {
fun accessTokenSigningAlgorithm(
@Qualifier("accessTokenPublicKey")
accessTokenPublicKey: RSAPublicKey
): Algorithm {
return Algorithm.RSA256(
accessTokenPublicKey(),
accessTokenPublicKey,
accessTokenPrivateKey()
)
}
@Bean("accessTokenPublicKey")
fun accessTokenPublicKey(): RSAPublicKey {
val keySpecX509 = getKeySpec(accessTokenProperties.keyPair.public, ::X509EncodedKeySpec)
return keyFactory.generatePublic(keySpecX509) as RSAPublicKey
}
@Bean("accessTokenPrivateKey")
fun accessTokenPrivateKey(): RSAPrivateKey {
val keySpecPKCS8 = getKeySpec(accessTokenProperties.keyPair.private, ::PKCS8EncodedKeySpec)
@ -37,22 +35,6 @@ class AccessTokenBeanConfig(private val accessTokenProperties: AccessTokenProper
return keyFactory.generatePrivate(keySpecPKCS8) as RSAPrivateKey
}
private fun <T> getKeySpec(key: String, keySpecFn: (ByteArray) -> T): T {
val rawKey = getRawKey(key)
return Base64.getDecoder()
.decode(rawKey)
.let(keySpecFn)
}
private fun getRawKey(key: String): String {
return key
.replace("-----BEGIN .+KEY-----".toRegex(), emptyString())
.replace("-----END .+KEY-----".toRegex(), emptyString())
.replace("\n", emptyString())
.trim()
}
companion object {
val keyFactory: KeyFactory = KeyFactory.getInstance("RSA")
}

View File

@ -4,8 +4,7 @@ plugins {
}
dependencies {
implementation(project(":auth-jwt-core"))
implementation(project(":common"))
implementation(project(":common-spring-security"))
implementation("org.springframework.security:spring-security-oauth2-jose")

View File

@ -1,6 +1,32 @@
package ru.touchin.auth.security.jwt.configurations
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import ru.touchin.auth.security.jwt.properties.AccessTokenPublicProperties
import ru.touchin.auth.security.jwt.utils.JwtUtils.getKeySpec
import java.security.KeyFactory
import java.security.interfaces.RSAPublicKey
import java.security.spec.X509EncodedKeySpec
@ComponentScan("ru.touchin.auth.security.jwt.http.configurators")
class JwtConfiguration
@ComponentScan(
"ru.touchin.auth.security.jwt.http.configurators",
"ru.touchin.auth.security.jwt.properties",
)
@ConfigurationPropertiesScan("ru.touchin.auth.security.jwt.properties")
class JwtConfiguration {
@Bean("accessTokenPublicKey")
fun accessTokenPublicKey(
accessTokenPublicProperties: AccessTokenPublicProperties,
): RSAPublicKey {
val keySpecX509 = getKeySpec(accessTokenPublicProperties.keyPair.public, ::X509EncodedKeySpec)
return keyFactory.generatePublic(keySpecX509) as RSAPublicKey
}
companion object {
val keyFactory: KeyFactory = KeyFactory.getInstance("RSA")
}
}

View File

@ -6,7 +6,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.oauth2.jwt.JwtDecoder
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
import org.springframework.stereotype.Component
import ru.touchin.auth.core.tokens.access.properties.AccessTokenProperties
import ru.touchin.auth.security.jwt.properties.AccessTokenPublicProperties
import ru.touchin.common.spring.Ordered
import ru.touchin.common.spring.security.http.configurators.HttpSecurityConfigurator
import java.security.interfaces.RSAPublicKey
@ -16,7 +16,7 @@ import java.security.interfaces.RSAPublicKey
class JwtHttpSecurityConfigurator(
@Qualifier("accessTokenPublicKey")
private val accessTokenPublicKey: RSAPublicKey,
private val accessTokenProperties: AccessTokenProperties
private val accessTokenProperties: AccessTokenPublicProperties
) : HttpSecurityConfigurator {
override fun configure(http: HttpSecurity) {

View File

@ -0,0 +1,15 @@
package ru.touchin.auth.security.jwt.properties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.ConstructorBinding
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm
data class AccessTokenKeyPair(val public: String)
@ConstructorBinding
@ConfigurationProperties(prefix = "token.access")
data class AccessTokenPublicProperties(
val keyPair: AccessTokenKeyPair,
val issuer: String,
val signatureAlgorithm: SignatureAlgorithm
)

View File

@ -0,0 +1,24 @@
package ru.touchin.auth.security.jwt.utils
import ru.touchin.common.string.StringUtils.emptyString
import java.util.*
object JwtUtils {
fun <T> getKeySpec(key: String, keySpecFn: (ByteArray) -> T): T {
val rawKey = getRawKey(key)
return Base64.getDecoder()
.decode(rawKey)
.let(keySpecFn)
}
private fun getRawKey(key: String): String {
return key
.replace("-----BEGIN .+KEY-----".toRegex(), emptyString())
.replace("-----END .+KEY-----".toRegex(), emptyString())
.replace("\n", emptyString())
.trim()
}
}