Skip to content

Commit

Permalink
reverted changes in ConvertingAuthenticationManager and CustomAuthent…
Browse files Browse the repository at this point in the history
…icationBasicConverter
  • Loading branch information
nulls committed Jul 20, 2023
1 parent 200d72a commit cf99ae6
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.saveourtool.save.authservice.security

import com.saveourtool.save.authservice.service.AuthenticationUserDetailsService
import com.saveourtool.save.authservice.utils.AuthenticationDetails
import com.saveourtool.save.authservice.utils.IdentitySourceAwareUserDetails
import com.saveourtool.save.authservice.utils.extractUserNameAndIdentitySource
import com.saveourtool.save.authservice.utils.username

import org.springframework.security.authentication.BadCredentialsException
Expand All @@ -9,15 +12,18 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.Authentication
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toMono
import reactor.kotlin.core.publisher.cast
import reactor.kotlin.core.publisher.switchIfEmpty

/**
* Implementation of `ReactiveAuthenticationManager` that doesn't check user credentials
* and simply authenticates every user with username. Should be used in secure environment,
* where user identity is already guaranteed.
*/
@Component
class ConvertingAuthenticationManager : ReactiveAuthenticationManager {
class ConvertingAuthenticationManager(
private val authenticationUserDetailsService: AuthenticationUserDetailsService
) : ReactiveAuthenticationManager {
/**
* Authenticate user, by checking the received data, which converted into UsernamePasswordAuthenticationToken
* by [CustomAuthenticationBasicConverter] with record in DB
Expand All @@ -26,20 +32,34 @@ class ConvertingAuthenticationManager : ReactiveAuthenticationManager {
* @throws BadCredentialsException in case of bad credentials
*/
override fun authenticate(authentication: Authentication): Mono<Authentication> = if (authentication is UsernamePasswordAuthenticationToken) {
val username = authentication.username()
if (authentication.details != null && authentication.details is AuthenticationDetails) {
val authenticationDetails = authentication.details as AuthenticationDetails
UsernamePasswordAuthenticationToken(
"${authenticationDetails.identitySource}:$username",
authentication.credentials,
authentication.authorities,
)
authentication.apply { details = authenticationDetails }
.toMono()
} else {
Mono.error { BadCredentialsException(authentication.username()) }
}
val (name, identitySource) = authentication.extractUserNameAndIdentitySource()
authenticationUserDetailsService.findByUsername(name)
.cast<IdentitySourceAwareUserDetails>()
.filter {
it.identitySource == identitySource
}
.switchIfEmpty {
Mono.error { BadCredentialsException(name) }
}
.onErrorMap {
BadCredentialsException(name)
}
.map {
it.toAuthenticationWithDetails(authentication)
}
} else {
Mono.error { BadCredentialsException("Unsupported authentication type ${authentication::class}") }
}

private fun IdentitySourceAwareUserDetails.toAuthenticationWithDetails(authentication: Authentication) =
UsernamePasswordAuthenticationToken(
"$identitySource:$username",
authentication.credentials,
authorities
).apply {
details = AuthenticationDetails(
id = id,
identitySource = identitySource,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.saveourtool.save.authservice.security

import com.saveourtool.save.authservice.service.AuthenticationUserDetailsService
import com.saveourtool.save.authservice.utils.AuthenticationDetails
import com.saveourtool.save.authservice.utils.IdentitySourceAwareUserDetails
import com.saveourtool.save.utils.AUTHORIZATION_SOURCE
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
Expand All @@ -11,38 +9,29 @@ import org.springframework.security.web.server.authentication.ServerHttpBasicAut
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.cast

/**
* Implementation of [ServerAuthenticationConverter] that embeds user identity source into [UsernamePasswordAuthenticationToken]
*/
@Component
class CustomAuthenticationBasicConverter(
private val authenticationUserDetailsService: AuthenticationUserDetailsService
) : ServerHttpBasicAuthenticationConverter(), ServerAuthenticationConverter {
class CustomAuthenticationBasicConverter : ServerHttpBasicAuthenticationConverter(),
ServerAuthenticationConverter {
/**
* Convert exchange, received from gateway into UsernamePasswordAuthenticationToken, specify source identity, laid
* by gateway into X-Authorization-Source header
*/
@Suppress("TOO_MANY_LINES_IN_LAMBDA")
override fun convert(exchange: ServerWebExchange): Mono<Authentication> = super.convert(exchange)
.cast<UsernamePasswordAuthenticationToken>()
.flatMap { authentication ->
val username = authentication.principal as String
val source = exchange.request.headers[AUTHORIZATION_SOURCE]?.firstOrNull()
authenticationUserDetailsService.findByUsername(username)
.cast<IdentitySourceAwareUserDetails>()
.map { userDetails ->
UsernamePasswordAuthenticationToken(
"$source:$username",
authentication.credentials,
userDetails.authorities
).apply {
details = AuthenticationDetails(
id = userDetails.id,
identitySource = source,
)
}
}
override fun convert(exchange: ServerWebExchange): Mono<Authentication> = super.convert(exchange).map { authentication ->
val name = (authentication as UsernamePasswordAuthenticationToken).principal as String
val source = exchange.request.headers[AUTHORIZATION_SOURCE]?.firstOrNull()
UsernamePasswordAuthenticationToken(
"$source:$name",
authentication.credentials as String
).apply {
details = AuthenticationDetails(
id = -1L,
identitySource = source,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,3 @@ const val AUTHORIZATION_SOURCE = "X-Authorization-Source"
*/
@Suppress("NON_EXPORTABLE_TYPE")
const val DEFAULT_SETUP_SH_TIMEOUT_MILLIS: Long = 60_000L

/**
* Separator for name and source of user
*/
const val AUTH_SEPARATOR = "@SAVE@"

0 comments on commit cf99ae6

Please sign in to comment.