Skip to content

Instantly share code, notes, and snippets.

@senthilsivanath
Last active May 31, 2021 07:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save senthilsivanath/4ff8906d0e5dc89414d7cc27954cb96f to your computer and use it in GitHub Desktop.
Save senthilsivanath/4ff8906d0e5dc89414d7cc27954cb96f to your computer and use it in GitHub Desktop.
Auth
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager
import org.springframework.security.core.Authentication
import org.springframework.security.core.userdetails.ReactiveUserDetailsService
import org.springframework.security.web.server.authentication.AuthenticationWebFilter
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository
import org.springframework.security.web.server.util.matcher.NegatedServerWebExchangeMatcher
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
@Component
class AppSecurityConfig {
@Autowired
private lateinit var jwtAuthenticationConverter: JwtAuthenticationConverter
@Autowired
private lateinit var userDetailsService: ReactiveUserDetailsService
class CustomReactiveAuthenticationManager(userDetailsService: ReactiveUserDetailsService?) : UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService) {
override fun authenticate(authentication: Authentication): Mono<Authentication> {
return if (authentication.isAuthenticated) {
Mono.just(authentication)
} else super.authenticate(authentication)
}
}
fun authenticationWebFilter(): AuthenticationWebFilter? {
val authenticationWebFilter = AuthenticationWebFilter(CustomReactiveAuthenticationManager(userDetailsService))
authenticationWebFilter.setServerAuthenticationConverter(jwtAuthenticationConverter)
authenticationWebFilter.setRequiresAuthenticationMatcher((NegatedServerWebExchangeMatcher(ServerWebExchangeMatchers.pathMatchers("SOMEURL"))))
authenticationWebFilter.setSecurityContextRepository(NoOpServerSecurityContextRepository.getInstance())
return authenticationWebFilter
}
}
@Configuration
class JwtAuthenticationConverter : ServerAuthenticationConverter {
private val logger = KotlinLogging.logger {}
@Autowired
private lateinit var tokenProvider: TokenProvider
override fun convert(exchange: ServerWebExchange): Mono<Authentication> {
return mono {
try {
val token = getBearerToken(exchange)
val authentication = tokenProvider.getAuthentication(token)
authentication
} catch (e: Exception) {
logger.error("Exception while processing auth", e)
throw UnauthorizedException()
}
}
}
private suspend fun getBearerToken(exchange: ServerWebExchange): String {
val authToken = exchange.request.headers.getFirst(HttpHeaders.AUTHORIZATION)!!
try {
// Verify okta token
} catch (e: InvalidTokenException // Replace with right exception) {
logger.error("Exception while processing auth", e)
throw UnauthorizedException()
}
return authToken
}
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
import org.springframework.security.config.web.server.SecurityWebFiltersOrder
import org.springframework.security.config.web.server.ServerHttpSecurity
import org.springframework.security.web.server.SecurityWebFilterChain
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository
import org.springframework.security.web.server.savedrequest.NoOpServerRequestCache
import sh.radical.auth.configurations.RadicalSecurityConfig
import sh.radical.orderservice.utils.PLAYGROUND_URL
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
class SecurityConfig {
@Autowired
private lateinit var appSecurityConfig: AppSecurityConfig
@Bean
fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain? {
return http
.requestCache().requestCache(NoOpServerRequestCache.getInstance()).and()
.csrf().disable()
.authorizeExchange()
.and()
.httpBasic().disable()
.formLogin().disable()
.authorizeExchange()
.pathMatchers(PLAYGROUND_URL).permitAll()
.anyExchange().authenticated()
.and()
.addFilterAt(appSecurityConfig.authenticationWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
.build()
}
}
val context = ReactiveSecurityContextHolder.getContext().awaitSingle()
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.nimbusds.jwt.SignedJWT
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.User
import sh.radical.auth.keycloak.entities.AccessToken
import java.util.stream.Collectors
@Configuration
class TokenProvider {
@Autowired
lateinit var objectMapper: ObjectMapper
@Autowired
lateinit var authProperties: AuthProperties
fun getAuthentication(token: String): Authentication {
val payload = SignedJWT.parse(token).payload.toString()
val accessToken = objectMapper.readValue<AccessToken>(payload)
var authoritiesData = listOf<String>()
accessToken.resourceAccess?.get(authProperties.clientName)?.let {
authoritiesData = authoritiesData.plus(it.roles)
}
accessToken.authorization?.let {
it.permissions[0].claims.scopes?.let { scopes ->
authoritiesData = authoritiesData.plus(scopes)
}
it.permissions[0].scopes?.let { scopes ->
authoritiesData = authoritiesData.plus(scopes)
}
}
val authorities: Collection<GrantedAuthority?> = authoritiesData.stream()
.map { role: String? -> SimpleGrantedAuthority(role) }
.collect(Collectors.toList())
val userId = accessToken.sub
val principal = User(userId, "", authorities)
return UsernamePasswordAuthenticationToken(principal, token, authorities)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment