auth server configuration
@EnableWebSecurity
@Configuration
class WebSecurityConfig {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http
.cors { cors -> cors.disable() }
.csrf { csrf -> csrf.disable() }
.authorizeRequests().anyRequest().authenticated()
http.formLogin()
return http.build()
}
@Bean
fun passwordEncoder() = BCryptPasswordEncoder()
}
@Configuration
class AuthServerConfig {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
fun clientSecurityFilterChain(http: HttpSecurity): SecurityFilterChain? {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)
return http.formLogin().and().build()
}
@Bean
fun providerSettings(): ProviderSettings = ProviderSettings
.builder()
.issuer("http://localhost:8283")
.build()
@Bean
fun jwkSource(): JWKSource<SecurityContext> {
val rsaKey = generateRsaKey()
val set = JWKSet(rsaKey)
return JWKSource { selector: JWKSelector, _: SecurityContext? ->
selector.select(set)
}
}
private fun generateRsaKey(): RSAKey {
val keyPair = KeyPairGenerator.getInstance("RSA")
keyPair.initialize(2048)
val keys = keyPair.generateKeyPair()
return try {
RSAKey.Builder(keys.public as RSAPublicKey).privateKey(keys.private)
.keyID(UUID.randomUUID().toString()).build()
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException("Error while generating rsa keys")
}
}
}
UserdetailsService and RegisteredClientRepository
@Component
class CustomUserDetailsService(
private val authUserRepository: AuthUserRepository
) : UserDetailsService {
override fun loadUserByUsername(username: String) = authUserRepository.findByEmailAndDeletedFalse(username)
}
@Component
class CustomRegisteredClientRepository(
private val clientRepository: ClientRepository,
private val encoder: BCryptPasswordEncoder
) : RegisteredClientRepository {
override fun save(registeredClient: RegisteredClient?) {
registeredClient?.run {
val client = CustomRegisteredClient(
clientId,
clientIdIssuedAt?.toEpochMilli(),
encoder.encode(clientSecret),
clientSecretExpiresAt?.toEpochMilli(),
clientName,
clientAuthenticationMethods.map { it.value },
authorizationGrantTypes.map { it.value },
redirectUris.toList(),
scopes.toList(),
clientSettings.isRequireAuthorizationConsent,
tokenSettings.accessTokenTimeToLive,
tokenSettings.refreshTokenTimeToLive
)
clientRepository.save(client)
}
}
override fun findById(id: String?): RegisteredClient? {
id?.let {
val client = clientRepository.findById(it)
if (client.isPresent) return client.get().toRegisteredClient()
}
return null
}
override fun findByClientId(clientId: String?): RegisteredClient? {
clientId?.let {
val client = clientRepository.findByClientId(clientId)
return client?.toRegisteredClient()
}
return null
}
}
// initilizing user and client, saving user and client to mongodb
@Component
class ContextRefreshEvent(
private val clientRepository: ClientRepository,
private val passwordEncoder: BCryptPasswordEncoder,
private val userRepository: AuthUserRepository
) {
@EventListener(ContextRefreshedEvent::class)
fun contextRefreshedEvent() {
if (clientRepository.findByClientName("demo") == null) {
val client = CustomRegisteredClient(
"demo",
Date().time,
passwordEncoder.encode("12345"),
Date().time.plus(3600),
"demo",
listOf(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.value),
listOf(AuthorizationGrantType.AUTHORIZATION_CODE.value, AuthorizationGrantType.REFRESH_TOKEN.value),
listOf("http://127.0.0.1:3000/authorized"),
listOf(OidcScopes.OPENID),
true,
Duration.ofHours(1),
Duration.ofHours(3),
)
clientRepository.save(client)
println("====== auth client initialized =====")
}
if (userRepository.findByEmailAndDeletedFalse("botir") == null) {
val user = AuthUser(
"minfin",
passwordEncoder.encode("12345"),
"botir",
true,
UserRole.ADMIN
)
userRepository.save(user)
println("User initialized")
}
}
}
Client app security configuration
@Configuration
class WebSecurityConfig {
@Bean
fun filterChain(http: HttpSecurity): SecurityFilterChain {
http
.cors { cors -> cors.disable() }
.csrf { csrf -> csrf.disable() }
.sessionManagement { session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) }
.oauth2ResourceServer { server ->
server.jwt().jwkSetUri("http://localhost:8283/oauth2/jwks")
}
.authorizeRequests { auth ->
auth.anyRequest().authenticated()
}
return http.build()
}
}
@RestController
class TestController {
@GetMapping
fun test() = "Test ..."
}
Is there any way to make the client app validates every request with auth server. Now it is only validating for the first time, and it is working even if I shoot down the auth server.