From 5e84eb2bb36f3556516e7cf1161410a16984a336 Mon Sep 17 00:00:00 2001 From: Alexander Buntakov Date: Tue, 15 Jun 2021 00:14:21 +0300 Subject: [PATCH] fix security modules --- README.md | 11 ++++++ .../configurations/AuthCoreConfiguration.kt | 2 +- .../configurations/AuthTokenConfiguration.kt | 2 -- .../AuthTokenDatabaseConfiguration.kt | 1 - ...enService.kt => AccessTokenCoreService.kt} | 2 +- ...pl.kt => JwtAccessTokenCoreServiceImpl.kt} | 4 +-- ...nService.kt => RefreshTokenCoreService.kt} | 2 +- ...Impl.kt => RefreshTokenCoreServiceImpl.kt} | 4 +-- auth-jwt/build.gradle.kts | 13 +++++++ .../jwt/configurations/JwtConfiguration.kt | 6 ++++ .../JwtHttpSecurityConfigurator.kt | 36 +++++++++++++++++++ .../DefaultSecurityConfiguration.kt | 21 +++++------ ...thorizeRequestsHttpSecurityConfigurator.kt | 25 +++++++++++++ .../BasicHttpSecurityConfigurator.kt | 17 +++++++++ .../CorsHttpSecurityConfigurator.kt | 17 +++++++++ .../CsrfHttpSecurityConfigurator.kt | 17 +++++++++ .../configurators/HttpSecurityConfigurator.kt | 9 +++++ settings.gradle.kts | 1 + 18 files changed, 167 insertions(+), 23 deletions(-) rename auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/{AccessTokenService.kt => AccessTokenCoreService.kt} (87%) rename auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/{JwtAccessTokenServiceImpl.kt => JwtAccessTokenCoreServiceImpl.kt} (96%) rename auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/{RefreshTokenService.kt => RefreshTokenCoreService.kt} (88%) rename auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/{RefreshTokenServiceImpl.kt => RefreshTokenCoreServiceImpl.kt} (97%) create mode 100644 auth-jwt/build.gradle.kts create mode 100644 auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/configurations/JwtConfiguration.kt create mode 100644 auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/http/configurators/JwtHttpSecurityConfigurator.kt create mode 100644 common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/AuthorizeRequestsHttpSecurityConfigurator.kt create mode 100644 common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/BasicHttpSecurityConfigurator.kt create mode 100644 common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CorsHttpSecurityConfigurator.kt create mode 100644 common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CsrfHttpSecurityConfigurator.kt create mode 100644 common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/HttpSecurityConfigurator.kt diff --git a/README.md b/README.md index d032b32..06f2446 100644 --- a/README.md +++ b/README.md @@ -148,3 +148,14 @@ token.refresh: prefix: RT- timeToLive: PT2H # 2 hours ``` + +Генерация ключей: + +```bash +openssl genrsa -out private.pem 4096 +openssl rsa -in private.pem -pubout -out public.pem +openssl pkcs8 -topk8 -inform PEM -outform DER -in private.pem -nocrypt > pkcs8_key + +cat pkcs8_key | base64 +cat public.pem +``` diff --git a/auth-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthCoreConfiguration.kt b/auth-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthCoreConfiguration.kt index c88ad41..f4e2a7d 100644 --- a/auth-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthCoreConfiguration.kt +++ b/auth-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthCoreConfiguration.kt @@ -8,7 +8,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder @ComponentScan("ru.touchin.auth.core") -@ConfigurationPropertiesScan +@ConfigurationPropertiesScan("ru.touchin.auth.core") class AuthCoreConfiguration { @Bean diff --git a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenConfiguration.kt b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenConfiguration.kt index 201edc4..4dec698 100644 --- a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenConfiguration.kt +++ b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenConfiguration.kt @@ -2,10 +2,8 @@ package ru.touchin.auth.core.configurations import org.springframework.boot.context.properties.ConfigurationPropertiesScan import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Import -@Configuration @Import(AuthCoreConfiguration::class) @ComponentScan("ru.touchin.auth.core.tokens") @ConfigurationPropertiesScan("ru.touchin.auth.core.tokens") diff --git a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenDatabaseConfiguration.kt b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenDatabaseConfiguration.kt index 36e7030..6b28d3f 100644 --- a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenDatabaseConfiguration.kt +++ b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/configurations/AuthTokenDatabaseConfiguration.kt @@ -4,7 +4,6 @@ import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Import -@Configuration @Import(AuthCoreDatabaseConfiguration::class) @EntityScan("ru.touchin.auth.core.tokens") class AuthTokenDatabaseConfiguration diff --git a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/AccessTokenService.kt b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/AccessTokenCoreService.kt similarity index 87% rename from auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/AccessTokenService.kt rename to auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/AccessTokenCoreService.kt index cc6d910..acc9678 100644 --- a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/AccessTokenService.kt +++ b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/AccessTokenCoreService.kt @@ -3,7 +3,7 @@ package ru.touchin.auth.core.tokens.access.services import ru.touchin.auth.core.tokens.access.dto.AccessToken import ru.touchin.auth.core.tokens.access.dto.AccessTokenRequest -interface AccessTokenService { +interface AccessTokenCoreService { fun create(accessTokenRequest: AccessTokenRequest): AccessToken diff --git a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/JwtAccessTokenServiceImpl.kt b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/JwtAccessTokenCoreServiceImpl.kt similarity index 96% rename from auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/JwtAccessTokenServiceImpl.kt rename to auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/JwtAccessTokenCoreServiceImpl.kt index 0d7f812..110cf86 100644 --- a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/JwtAccessTokenServiceImpl.kt +++ b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/access/services/JwtAccessTokenCoreServiceImpl.kt @@ -13,10 +13,10 @@ import java.time.ZoneId import java.util.* @Service -class JwtAccessTokenServiceImpl( +class JwtAccessTokenCoreServiceImpl( private val accessTokenProperties: AccessTokenProperties, private val accessTokenSigningAlgorithm: Algorithm -) : AccessTokenService { +) : AccessTokenCoreService { private fun sign(builder: JWTCreator.Builder) = builder.sign(accessTokenSigningAlgorithm) diff --git a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenService.kt b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenCoreService.kt similarity index 88% rename from auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenService.kt rename to auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenCoreService.kt index b364a96..b87552f 100644 --- a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenService.kt +++ b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenCoreService.kt @@ -3,7 +3,7 @@ package ru.touchin.auth.core.tokens.refresh.services import ru.touchin.auth.core.tokens.refresh.dto.RefreshToken import ru.touchin.auth.core.tokens.refresh.services.dto.NewRefreshToken -interface RefreshTokenService { +interface RefreshTokenCoreService { fun get(value: String): RefreshToken fun create(token: NewRefreshToken): RefreshToken diff --git a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenServiceImpl.kt b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenCoreServiceImpl.kt similarity index 97% rename from auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenServiceImpl.kt rename to auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenCoreServiceImpl.kt index 0177b4f..dbad070 100644 --- a/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenServiceImpl.kt +++ b/auth-jwt-core/src/main/kotlin/ru/touchin/auth/core/tokens/refresh/services/RefreshTokenCoreServiceImpl.kt @@ -20,13 +20,13 @@ import ru.touchin.common.random.SecureRandomStringGenerator import java.time.ZonedDateTime @Service -class RefreshTokenServiceImpl( +class RefreshTokenCoreServiceImpl( private val refreshTokenProperties: RefreshTokenProperties, private val refreshTokenRepository: RefreshTokenRepository, private val userRepository: UserRepository, private val deviceRepository: DeviceRepository, private val scopeRepository: ScopeRepository, -) : RefreshTokenService { +) : RefreshTokenCoreService { @Transactional(readOnly = true) override fun get(value: String): RefreshToken { diff --git a/auth-jwt/build.gradle.kts b/auth-jwt/build.gradle.kts new file mode 100644 index 0000000..187cbba --- /dev/null +++ b/auth-jwt/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("kotlin") + id("kotlin-spring") +} + +dependencies { + implementation(project(":auth-jwt-core")) + + implementation(project(":common-spring-security")) + + implementation("org.springframework.security:spring-security-oauth2-jose") + implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") +} diff --git a/auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/configurations/JwtConfiguration.kt b/auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/configurations/JwtConfiguration.kt new file mode 100644 index 0000000..17aae35 --- /dev/null +++ b/auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/configurations/JwtConfiguration.kt @@ -0,0 +1,6 @@ +package ru.touchin.auth.security.jwt.configurations + +import org.springframework.context.annotation.ComponentScan + +@ComponentScan("ru.touchin.auth.security.jwt.http.configurators") +class JwtConfiguration diff --git a/auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/http/configurators/JwtHttpSecurityConfigurator.kt b/auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/http/configurators/JwtHttpSecurityConfigurator.kt new file mode 100644 index 0000000..aebe4e0 --- /dev/null +++ b/auth-jwt/src/main/kotlin/ru/touchin/auth/security/jwt/http/configurators/JwtHttpSecurityConfigurator.kt @@ -0,0 +1,36 @@ +package ru.touchin.auth.security.jwt.http.configurators + +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.core.annotation.Order +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.common.spring.Ordered +import ru.touchin.common.spring.security.http.configurators.HttpSecurityConfigurator +import java.security.interfaces.RSAPublicKey + +@Order(Ordered.HIGH) +@Component +class JwtHttpSecurityConfigurator( + @Qualifier("accessTokenPublicKey") + private val accessTokenPublicKey: RSAPublicKey, + private val accessTokenProperties: AccessTokenProperties +) : HttpSecurityConfigurator { + + override fun configure(http: HttpSecurity) { + http.oauth2ResourceServer { + it.jwt { jwt -> + jwt.decoder(getJwtDecoder()) + } + } + } + + private fun getJwtDecoder(): JwtDecoder { + return NimbusJwtDecoder.withPublicKey(accessTokenPublicKey) + .signatureAlgorithm(accessTokenProperties.signatureAlgorithm) + .build() + } + +} diff --git a/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/configurations/DefaultSecurityConfiguration.kt b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/configurations/DefaultSecurityConfiguration.kt index 7036642..25b3a17 100644 --- a/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/configurations/DefaultSecurityConfiguration.kt +++ b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/configurations/DefaultSecurityConfiguration.kt @@ -5,26 +5,21 @@ import org.springframework.context.annotation.Configuration import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter -import ru.touchin.common.spring.security.url.interceptors.UrlExpressionRegistryInterceptor +import ru.touchin.common.spring.security.http.configurators.HttpSecurityConfigurator @Configuration -@ComponentScan("ru.touchin.common.spring.security.url.interceptors") +@ComponentScan( + "ru.touchin.common.spring.security.url.interceptors", + "ru.touchin.common.spring.security.http.configurators", +) @EnableGlobalMethodSecurity(prePostEnabled = true) class DefaultSecurityConfiguration( - private val urlExpressionRegistryInterceptors: List, + private val httpSecurityConfigurators: List, ) : WebSecurityConfigurerAdapter() { override fun configure(http: HttpSecurity) { - http - .cors().disable() - .csrf().disable() - .httpBasic().disable() - .authorizeRequests { urlExpressionRegistry -> - urlExpressionRegistryInterceptors.forEach { - it.invoke(urlExpressionRegistry) - } - - urlExpressionRegistry.anyRequest().authenticated() + httpSecurityConfigurators.forEach { + it.configure(http) } } diff --git a/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/AuthorizeRequestsHttpSecurityConfigurator.kt b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/AuthorizeRequestsHttpSecurityConfigurator.kt new file mode 100644 index 0000000..7d0dfc1 --- /dev/null +++ b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/AuthorizeRequestsHttpSecurityConfigurator.kt @@ -0,0 +1,25 @@ +package ru.touchin.common.spring.security.http.configurators + +import org.springframework.core.annotation.Order +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.stereotype.Component +import ru.touchin.common.spring.Ordered +import ru.touchin.common.spring.security.url.interceptors.UrlExpressionRegistryInterceptor + +@Order(Ordered.NORMAL) +@Component +class AuthorizeRequestsHttpSecurityConfigurator( + private val urlExpressionRegistryInterceptors: List, +) : HttpSecurityConfigurator { + + override fun configure(http: HttpSecurity) { + http.authorizeRequests { urlExpressionRegistry -> + urlExpressionRegistryInterceptors.forEach { + it.invoke(urlExpressionRegistry) + } + + urlExpressionRegistry.anyRequest().authenticated() + } + } + +} diff --git a/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/BasicHttpSecurityConfigurator.kt b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/BasicHttpSecurityConfigurator.kt new file mode 100644 index 0000000..ebd9869 --- /dev/null +++ b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/BasicHttpSecurityConfigurator.kt @@ -0,0 +1,17 @@ +package ru.touchin.common.spring.security.http.configurators + +import org.springframework.core.annotation.Order +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.stereotype.Component +import ru.touchin.common.spring.Ordered + +@Order(Ordered.LOW) +@Component +class BasicHttpSecurityConfigurator : HttpSecurityConfigurator { + + override fun configure(http: HttpSecurity) { + // TODO: user properties + http.httpBasic().disable() + } + +} diff --git a/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CorsHttpSecurityConfigurator.kt b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CorsHttpSecurityConfigurator.kt new file mode 100644 index 0000000..821afcd --- /dev/null +++ b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CorsHttpSecurityConfigurator.kt @@ -0,0 +1,17 @@ +package ru.touchin.common.spring.security.http.configurators + +import org.springframework.core.annotation.Order +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.stereotype.Component +import ru.touchin.common.spring.Ordered + +@Order(Ordered.LOW) +@Component +class CorsHttpSecurityConfigurator : HttpSecurityConfigurator { + + override fun configure(http: HttpSecurity) { + // TODO: user properties + http.cors().disable() + } + +} diff --git a/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CsrfHttpSecurityConfigurator.kt b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CsrfHttpSecurityConfigurator.kt new file mode 100644 index 0000000..f50656b --- /dev/null +++ b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/CsrfHttpSecurityConfigurator.kt @@ -0,0 +1,17 @@ +package ru.touchin.common.spring.security.http.configurators + +import org.springframework.core.annotation.Order +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.stereotype.Component +import ru.touchin.common.spring.Ordered + +@Order(Ordered.LOW) +@Component +class CsrfHttpSecurityConfigurator : HttpSecurityConfigurator { + + override fun configure(http: HttpSecurity) { + // TODO: use properties + http.csrf().disable() + } + +} diff --git a/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/HttpSecurityConfigurator.kt b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/HttpSecurityConfigurator.kt new file mode 100644 index 0000000..c3f32b4 --- /dev/null +++ b/common-spring-security/src/main/kotlin/ru/touchin/common/spring/security/http/configurators/HttpSecurityConfigurator.kt @@ -0,0 +1,9 @@ +package ru.touchin.common.spring.security.http.configurators + +import org.springframework.security.config.annotation.web.builders.HttpSecurity + +interface HttpSecurityConfigurator { + + fun configure(http: HttpSecurity) + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 45f8200..8f5523f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,3 +41,4 @@ include("response-wrapper-spring-web") include("settings-spring-jpa") include("auth-core") include("auth-jwt-core") +include("auth-jwt")