diff --git a/Spring BFF/resource/ResourceServerConfig.kt b/Spring BFF/resource/ResourceServerConfig.kt deleted file mode 100644 index 9251555..0000000 --- a/Spring BFF/resource/ResourceServerConfig.kt +++ /dev/null @@ -1,213 +0,0 @@ -package com.example.timesheetapi.auth.security - -import com.example.timesheetapi.auth.security.filters.IPWhiteListFilter -import com.example.timesheetapi.auth.security.filters.ValidEndPointFilter -import com.example.timesheetapi.auth.security.handlers.AccessDeniedHandler -import com.example.timesheetapi.auth.security.handlers.AuthenticationEntryPoint -import com.nimbusds.jose.JOSEObject -import org.springframework.beans.factory.annotation.Value -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpStatus -import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver -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.core.userdetails.ReactiveUserDetailsService -import org.springframework.security.core.userdetails.User -import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder -import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder -import org.springframework.security.oauth2.server.resource.authentication.JwtReactiveAuthenticationManager -import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenReactiveAuthenticationManager -import org.springframework.security.oauth2.server.resource.introspection.NimbusReactiveOpaqueTokenIntrospector -import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenAuthenticationConverter -import org.springframework.security.web.server.SecurityWebFilterChain -import org.springframework.security.web.server.context.ServerSecurityContextRepository -import org.springframework.session.config.annotation.web.server.EnableSpringWebSession -import org.springframework.web.cors.CorsConfiguration -import org.springframework.web.server.ServerWebExchange -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/************************************************** SECURITY CONFIGURATION ********************************************/ -/**********************************************************************************************************************/ - -@Configuration -@EnableWebFluxSecurity -@EnableSpringWebSession -@EnableReactiveMethodSecurity(useAuthorizationManager = true) -internal class ResourceServerConfig() { - - // introspection URI (an authorization server endpoint) - @Value("\${auth.server.introspection.uri}") - lateinit var introspectionUri: String - - // public key for jw key set for verifying jwt tokens (an authorization server endpoint) - @Value("\${auth.server.jwkeyset.uri}") - lateinit var jwkSetUri: String - - // resource server client id - @Value("\${resource-server-client-id}") - lateinit var resourceServerClientID: String - - // resource server client secret - @Value("\${resource-server-client-secret}") - lateinit var resourceServerSecret: String - - @Bean - /* security filter chain for authentication & authorization (reactive) */ - /* this should be webSession stateless */ - fun resourceServerSecurityFilterChain( - http: ServerHttpSecurity, - authenticationEntryPoint: AuthenticationEntryPoint, - ipWhiteListFilter: IPWhiteListFilter, - accessDeniedHandler: AccessDeniedHandler, - validEndPointFilter: ValidEndPointFilter, - opaqueTokenConverter: ReactiveOpaqueTokenAuthenticationConverter, - customSecurityContextRepository: ServerSecurityContextRepository, - ): SecurityWebFilterChain { - - http - // disable csrf - .csrf { csrf -> - csrf.disable() - } - // configure HTTP Basic Authentication - .httpBasic { httpBasic -> - httpBasic.authenticationEntryPoint(authenticationEntryPoint) - } - // apply security context repository (direct assignment) - .securityContextRepository(customSecurityContextRepository) - // authorizations - .authorizeExchange { authorize -> - authorize - .pathMatchers("/index.html", "/", "/home", "/login").permitAll() - .pathMatchers("/logout").permitAll() - .anyExchange().authenticated() - } - // configure oauth 2.0 resource server -// .oauth2ResourceServer { oauth2 -> -// // choose appropriate authentication manager -// oauth2.authenticationManagerResolver( -// authenticationManagerResolver( -// jwtDecoder(), -// opaqueTokenIntrospector(), -// opaqueTokenConverter -// ) -// ).authenticationEntryPoint(authenticationEntryPoint) -// } - // apply ip-whitelist filter before http basic authentication - .addFilterBefore(ipWhiteListFilter, SecurityWebFiltersOrder.HTTP_BASIC) - // apply valid end-point filter before http basic authentication - .addFilterBefore(validEndPointFilter, SecurityWebFiltersOrder.HTTP_BASIC) - // handlers for any exceptions not handled elsewhere - .exceptionHandling { exceptionHandling -> - exceptionHandling.authenticationEntryPoint(authenticationEntryPoint) - exceptionHandling.accessDeniedHandler(accessDeniedHandler) - } - - return http.build() - } - - @Bean - fun userDetailsService(): ReactiveUserDetailsService { - val userDetails = User.withUsername("user") - .password("{noop}password") // {noop} indicates no password encoding - .roles("USER") - .build() - - return ReactiveUserDetailsService { username -> - Mono.justOrEmpty(userDetails.takeIf { it.username == username }) - } - } - - -// @Bean - // for choosing (resolving to) appropriate authentication manager - // useful for multi-tenant configurations - fun authenticationManagerResolver( - jwtDecoder: ReactiveJwtDecoder, - opaqueTokenIntrospector: NimbusReactiveOpaqueTokenIntrospector, - opaqueTokenConverter: ReactiveOpaqueTokenAuthenticationConverter - ): ReactiveAuthenticationManagerResolver { - - // authentication manager for jwt tokens (with no converter) - val jwtAuthManager = JwtReactiveAuthenticationManager(jwtDecoder) - - // authentication manager for opaque tokens (with token >>> authentication object, converter) - val opaqueAuthManager = OpaqueTokenReactiveAuthenticationManager(opaqueTokenIntrospector) - opaqueAuthManager.setAuthenticationConverter(opaqueTokenConverter) - - // resolving conditions - return ReactiveAuthenticationManagerResolver { exchange -> - isJwtValid(exchange) - .flatMap { isValidJwt -> - if (isValidJwt) { - Mono.just(jwtAuthManager) - } else { - Mono.just(opaqueAuthManager) - } - } - } - - } - - // helper function for checking if access token is a JSON WEB TOKEN (J.W.T.) - private fun isJwtValid(exchange: ServerWebExchange): Mono { - // resolve Bearer Token asynchronously - return Mono.fromCallable { - val headers: HttpHeaders = exchange.request.headers - val authorizationHeader: String? = headers.getFirst(HttpHeaders.AUTHORIZATION) - - authorizationHeader?.let { - if (it.startsWith("Bearer ")) { - return@fromCallable it.substring(7) // extract token excluding "Bearer " - } - } - - // if Authorization header is missing or not in expected format - return@fromCallable null - } - .flatMap { accessToken -> - if (accessToken != null) { - // validate JWT asynchronously - Mono.fromCallable { - if (!accessToken.isNotBlank()) { - return@fromCallable false - } - - try { - val parts = JOSEObject.split(accessToken) - parts.size == 3 - } catch (ignored: Exception) { - false - } - } - } else { - // handle case where Bearer token is not found or in expected format - Mono.just(false) - } - } - } - - @Bean - // for introspecting opaque access tokens with the authorisation server - fun opaqueTokenIntrospector(): NimbusReactiveOpaqueTokenIntrospector { - return NimbusReactiveOpaqueTokenIntrospector(introspectionUri, resourceServerClientID, resourceServerSecret) - } - - @Bean - // for decoding JWT tokens - fun jwtDecoder() : ReactiveJwtDecoder { - return NimbusReactiveJwtDecoder - .withJwkSetUri(jwkSetUri) - .build() - } - -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/application.yaml b/Spring BFF/resource/application.yaml deleted file mode 100644 index b137a42..0000000 --- a/Spring BFF/resource/application.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Custom properties to ease configuration overrides -# on command-line or IDE launch configurations - -# server settings -scheme: http -hostname: localhost - -# reverse proxy -reverse-proxy-port: 7080 -reverse-proxy-uri: ${scheme}://${hostname}:${reverse-proxy-port} - -# resource server -resource-server-port: 8080 -resource-server-prefix: /resource -resource-server-uri: ${scheme}://${hostname}:${resource-server-port} - -# authorization server -authorization-server-prefix: /auth - -# current server settings -server: - port: ${resource-server-port} - ssl: - enabled: false - address: ${hostname} - -# authorization server endpoints -auth: - server: - jwkeyset: - uri: ${reverse-proxy-uri}${authorization-server-prefix}/oauth2/jwks - introspection: - uri: ${reverse-proxy-uri}${authorization-server-prefix}/oauth2/introspect - -# oauth2.0 client registrations (for auth server) -resource-server-client-id: resource_server -resource-server-client-secret: resource_server_secret \ No newline at end of file diff --git a/Spring BFF/resource/converters/JWTAuthenticationConverter.kt b/Spring BFF/resource/converters/JWTAuthenticationConverter.kt deleted file mode 100644 index 571514c..0000000 --- a/Spring BFF/resource/converters/JWTAuthenticationConverter.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.example.timesheetapi.auth.security.converters - -import org.springframework.core.convert.converter.Converter -import org.springframework.security.core.GrantedAuthority -import org.springframework.security.oauth2.jwt.Jwt -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken -import org.springframework.stereotype.Component -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/********************************************* AUTHENTICATION CONVERTER ***********************************************/ -/**********************************************************************************************************************/ - -@Component -internal class JwtAuthenticationConverter : Converter> { - - override fun convert(source: Jwt): Mono { - val authorities = listOf(GrantedAuthority { "READ" }) - - val customClaim = source.getClaimAsString("custom-claim") ?: "" - - return Mono.just(JwtAuthenticationToken(source, authorities, customClaim)) - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/converters/OpaqueTokenAuthenticationConverter.kt b/Spring BFF/resource/converters/OpaqueTokenAuthenticationConverter.kt deleted file mode 100644 index e57dad7..0000000 --- a/Spring BFF/resource/converters/OpaqueTokenAuthenticationConverter.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.example.timesheetapi.auth.security.converters - -import com.example.timesheetapi.api.utilities.functions.toMap -import com.example.timesheetapi.auth.security.objects.user.CustomOAuth2AuthenticatedPrincipal -import org.springframework.security.core.Authentication -import org.springframework.security.core.GrantedAuthority -import org.springframework.security.core.authority.AuthorityUtils -import org.springframework.security.core.authority.SimpleGrantedAuthority -import org.springframework.security.oauth2.core.OAuth2AccessToken -import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal -import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames -import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication -import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenAuthenticationConverter -import org.springframework.stereotype.Component -import org.springframework.util.StringUtils -import reactor.core.publisher.Mono -import java.util.stream.Collectors - -/**********************************************************************************************************************/ -/********************************************* AUTHENTICATION CONVERTER ***********************************************/ -/**********************************************************************************************************************/ - -@Component -internal class CustomReactiveOpaqueTokenAuthenticationConverter2 - : ReactiveOpaqueTokenAuthenticationConverter { - - override fun convert( - introspectedToken: String?, - authenticatedPrincipal: OAuth2AuthenticatedPrincipal - ): Mono { - - // get attributes - val attributes = authenticatedPrincipal.attributes - - // get authorities - var authorities: Collection? = AuthorityUtils.NO_AUTHORITIES - if (authenticatedPrincipal.attributes.containsKey("authorities")) { - authorities = - (authenticatedPrincipal.attributes["authorities"] as List?)!!.stream() - .map { auth: String? -> - SimpleGrantedAuthority( - auth - ) - } - .collect(Collectors.toUnmodifiableSet()) - } - - // get username - var username: String? = null - if (attributes.containsKey("username") - && StringUtils.hasText(attributes["username"] as String?) - ) { - username = attributes["username"] as String? - } - - // create access token - val accessToken = OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, - introspectedToken, - authenticatedPrincipal.getAttribute(IdTokenClaimNames.IAT), - authenticatedPrincipal.getAttribute(IdTokenClaimNames.EXP) - ) - - // create authentication principal object - val customOAuth2User = CustomOAuth2AuthenticatedPrincipal( - username!!, - authorities!!, - attributes - ) - - // create authentication object - val bearerTokenAuthentication = BearerTokenAuthentication( - customOAuth2User, - accessToken, - customOAuth2User.authorities - ) - - // return authentication object - return Mono.just(bearerTokenAuthentication) - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/filters/AuthenticationLoggingFilter.kt b/Spring BFF/resource/filters/AuthenticationLoggingFilter.kt deleted file mode 100644 index 65a27d3..0000000 --- a/Spring BFF/resource/filters/AuthenticationLoggingFilter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.example.timesheetapi.auth.security.filters - -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Component -import org.springframework.web.server.ServerWebExchange -import org.springframework.web.server.WebFilter -import org.springframework.web.server.WebFilterChain -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/******************************************************* FILTER *******************************************************/ -/**********************************************************************************************************************/ - -@Component -internal class AuthenticationLoggingFilter : WebFilter { - - private val logger = LoggerFactory.getLogger(AuthenticationLoggingFilter::class.java) - - override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono { - val requestId = exchange.request.headers.getFirst("Request-Id") - - return chain.filter(exchange) - .doOnSuccess { - logger.info("Completed processing request with id: $requestId") - } - .doOnError { - logger.info("Error processing request with id: $requestId") - } - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/filters/IPWhiteListFilter.kt b/Spring BFF/resource/filters/IPWhiteListFilter.kt deleted file mode 100644 index c4cc1a0..0000000 --- a/Spring BFF/resource/filters/IPWhiteListFilter.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.example.timesheetapi.auth.security.filters - -import org.springframework.http.HttpStatus -import org.springframework.stereotype.Component -import org.springframework.web.server.ServerWebExchange -import org.springframework.web.server.WebFilter -import org.springframework.web.server.WebFilterChain -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/******************************************************* FILTER *******************************************************/ -/**********************************************************************************************************************/ - -@Component -internal class IPWhiteListFilter : WebFilter { - - private val allowedIps = setOf( - "127.0.0.1" - ) - - override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono { - val remoteIp = exchange.request.remoteAddress?.address?.hostAddress - - return if (remoteIp in allowedIps) { - chain.filter(exchange) - } else { - exchange.response.statusCode = HttpStatus.FORBIDDEN - exchange.response.setComplete() - } - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/filters/ValidEndPointFilter.kt b/Spring BFF/resource/filters/ValidEndPointFilter.kt deleted file mode 100644 index 9d223f7..0000000 --- a/Spring BFF/resource/filters/ValidEndPointFilter.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.example.timesheetapi.auth.security.filters - -import com.example.timesheetapi.api.utilities.json.JacksonConfiguration -import com.fasterxml.jackson.databind.ObjectMapper -import org.springframework.context.ApplicationContext -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.http.server.PathContainer -import org.springframework.stereotype.Component -import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping -import org.springframework.web.server.ServerWebExchange -import org.springframework.web.server.WebFilter -import org.springframework.web.server.WebFilterChain -import org.springframework.web.util.pattern.PathPattern -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/******************************************************* FILTER *******************************************************/ -/**********************************************************************************************************************/ - -@Component -internal class ValidEndPointFilter( - private val endpointValidator: EndpointValidator -) : WebFilter { - - private val objectMapper: ObjectMapper = JacksonConfiguration.objectMapper - - override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono { - val request = exchange.request - val response = exchange.response - val requestPath = request.uri.path - - // if not valid - if (!endpointValidator.isValidEndPoint(requestPath)) { - - response.statusCode = HttpStatus.NOT_FOUND - response.headers.contentType = MediaType.APPLICATION_JSON - - val errorMessage = "Request Path is not valid" - val errorResponse = objectMapper.writeValueAsString(mapOf("Validation Error" to errorMessage)) - - return response.writeWith(Mono.just(response.bufferFactory().wrap(errorResponse.toByteArray()))) - } else { - - // if valid, proceed with the filter chain - return chain.filter(exchange) - } - - } -} - -@Component -internal class EndpointValidator( - private val applicationContext: ApplicationContext -) { - - // static endpoints to be combined with dynamic ones - private val staticEndpoints: Set = setOf( - "/logout", - // add other statically defined endpoints here - ) - - internal fun isValidEndPoint(requestPath: String): Boolean { - - // check static endpoints first - if (staticEndpoints.contains(requestPath)) { - return true - } - - // check dynamic endpoints - val handlerMappings = applicationContext.getBeansOfType(RequestMappingHandlerMapping::class.java).values - handlerMappings.forEach { handlerMapping -> - val mappings = handlerMapping.handlerMethods.keys - mappings.forEach { mapping -> - if (mapping.patternsCondition.patterns.any { - pattern -> - pathMatches(pattern, requestPath) - } == true) { - return true - } - } - } - return false - } - - private fun pathMatches(pattern: PathPattern, requestPath: String): Boolean { - val pathContainer = PathContainer.parsePath(requestPath) - return pattern.matches(pathContainer) - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/filters/not_used/CsrfTokenLoggerFilter.kt b/Spring BFF/resource/filters/not_used/CsrfTokenLoggerFilter.kt deleted file mode 100644 index b4781e0..0000000 --- a/Spring BFF/resource/filters/not_used/CsrfTokenLoggerFilter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.example.timesheetapi.auth.security.filters.not_used - -import org.springframework.security.web.server.csrf.CsrfToken -import org.springframework.stereotype.Component -import org.springframework.web.server.ServerWebExchange -import org.springframework.web.server.WebFilter -import org.springframework.web.server.WebFilterChain -import reactor.core.publisher.Mono -import java.util.logging.Logger - -/**********************************************************************************************************************/ -/************************************************* CSRF LOGGING FILTER ************************************************/ -/**********************************************************************************************************************/ - -@Component -class CsrfTokenLoggerFilter: WebFilter { - - private val logger: Logger = Logger.getLogger(CsrfTokenLoggerFilter::class.java.name) - - override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono { - val csrfTokenMono: Mono? = exchange.getAttribute(CsrfToken::class.java.name) - - return csrfTokenMono?.flatMap { token -> - if (token != null) { - logger.info("CSRF token ${token.token}") - } - chain.filter(exchange) - } ?: chain.filter(exchange) - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/filters/not_used/RequestValidationFilter.kt b/Spring BFF/resource/filters/not_used/RequestValidationFilter.kt deleted file mode 100644 index 41c32fb..0000000 --- a/Spring BFF/resource/filters/not_used/RequestValidationFilter.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.example.timesheetapi.auth.security.filters.not_used - -/**********************************************************************************************************************/ -/************************************************* VALIDATION FILTER **************************************************/ -/**********************************************************************************************************************/ - -//@Component -//internal class RequestValidationFilter() : WebFilter { -// -// private val objectMapper: ObjectMapper = JacksonConfiguration.objectMapper -// -// override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono { -// val request = exchange.request -// val response = exchange.response -// val requestId = request.headers.getFirst("Request-Id") -// -// // if not valid, exit filter chain, and return response -// if (requestId == null || requestId.isBlank()) { -// -// response.statusCode = HttpStatus.BAD_REQUEST -// response.headers.contentType = MediaType.APPLICATION_JSON -// -// val errorMessage = "Request-Id header is missing or empty" -// val errorResponse = objectMapper.writeValueAsString(mapOf("Validation Error" to errorMessage)) -// -// return response.writeWith(Mono.just(response.bufferFactory().wrap(errorResponse.toByteArray()))) -// } else { -// -// // if valid, proceed with the filter chain -// return chain.filter(exchange) -// } -// -// } -//} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/handlers/AccessDeniedHandler.kt b/Spring BFF/resource/handlers/AccessDeniedHandler.kt deleted file mode 100644 index ddee5dc..0000000 --- a/Spring BFF/resource/handlers/AccessDeniedHandler.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.example.timesheetapi.auth.security.handlers - -import com.example.timesheetapi.api.utilities.json.JacksonConfiguration -import com.fasterxml.jackson.databind.ObjectMapper -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler -import org.springframework.stereotype.Component -import org.springframework.web.server.ServerWebExchange -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/****************************************************** HANDLER *******************************************************/ -/**********************************************************************************************************************/ - -//* FOR AUTHORIZAION FAILURES *// - -@Component -internal class AccessDeniedHandler : ServerAccessDeniedHandler { - - private val objectMapper: ObjectMapper = JacksonConfiguration.objectMapper - - override fun handle( - exchange: ServerWebExchange?, - denied: org.springframework.security.access.AccessDeniedException? - ): Mono { - - val response = exchange?.response ?: return Mono.empty() - response.statusCode = HttpStatus.FORBIDDEN - - response.headers.contentType = MediaType.APPLICATION_JSON - response.headers.add("Authorization-Status", "Forbidden") - - val errorMessage = denied?.message ?: "Access Denied" - val errorResponse = objectMapper.writeValueAsString(mapOf("Authorization Failed" to errorMessage)) - val responseBody = response.bufferFactory().wrap(errorResponse.toByteArray()) - - return response.writeWith(Mono.just(responseBody)) - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/handlers/AuthenticationEntryPoint.kt b/Spring BFF/resource/handlers/AuthenticationEntryPoint.kt deleted file mode 100644 index 5b24849..0000000 --- a/Spring BFF/resource/handlers/AuthenticationEntryPoint.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.example.timesheetapi.auth.security.handlers - -import com.example.timesheetapi.api.utilities.json.JacksonConfiguration -import com.fasterxml.jackson.databind.ObjectMapper -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.security.core.AuthenticationException -import org.springframework.security.web.server.ServerAuthenticationEntryPoint -import org.springframework.stereotype.Component -import org.springframework.web.server.ServerWebExchange -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/****************************************************** HANDLER *******************************************************/ -/**********************************************************************************************************************/ - -//* FOR AUTHENTICATION FAILURES *// - -@Component -internal class AuthenticationEntryPoint() : ServerAuthenticationEntryPoint { - - private val objectMapper: ObjectMapper = JacksonConfiguration.objectMapper - - override fun commence(exchange: ServerWebExchange?, ex: AuthenticationException?): Mono { - - val response = exchange?.response ?: return Mono.empty() - response.statusCode = HttpStatus.UNAUTHORIZED - response.headers.contentType = MediaType.APPLICATION_JSON - response.headers.add("Authentication-Status", "Unauthorized") - - val errorMessage = ex?.message ?: "Unauthorized" - val errorResponse = objectMapper.writeValueAsString(mapOf("Authentication Failed" to errorMessage)) - val responseBody = response.bufferFactory().wrap(errorResponse.toByteArray()) - - return response.writeWith(Mono.just(responseBody)) - } - -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/objects/authentication/JWTAuthentication.kt b/Spring BFF/resource/objects/authentication/JWTAuthentication.kt deleted file mode 100644 index 92f6a1a..0000000 --- a/Spring BFF/resource/objects/authentication/JWTAuthentication.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.example.timesheetapi.auth.security.objects.authentication - -import org.springframework.security.core.GrantedAuthority -import org.springframework.security.oauth2.jwt.Jwt -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken - -/**********************************************************************************************************************/ -/*********************************************** AUTHENTICATION OBJECT ************************************************/ -/**********************************************************************************************************************/ - -internal class JWTAuthentication( - jwt: Jwt, - authorities: Collection, - private val customClaim: String -) : JwtAuthenticationToken(jwt, authorities) { - - fun getCustomClaim(): String { - return customClaim - } -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/objects/user/CustomOAuth2AuthenticatedPrincipal.kt b/Spring BFF/resource/objects/user/CustomOAuth2AuthenticatedPrincipal.kt deleted file mode 100644 index 429faec..0000000 --- a/Spring BFF/resource/objects/user/CustomOAuth2AuthenticatedPrincipal.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.example.timesheetapi.auth.security.objects.user - -import org.springframework.security.core.GrantedAuthority -import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal - -/**********************************************************************************************************************/ -/********************************************** USER / PRINCIPAL OBJECT ************************************************/ -/**********************************************************************************************************************/ - -internal class CustomOAuth2AuthenticatedPrincipal( - private val username: String, - private val authorities: Collection, - private val attributes: Map -) : OAuth2AuthenticatedPrincipal { - - override fun getName(): String { - return username - } - - override fun getAttributes(): Map { - return attributes - } - - override fun getAuthorities(): Collection { - return authorities - } - -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/repositories/SecurityContextRepository.kt b/Spring BFF/resource/repositories/SecurityContextRepository.kt deleted file mode 100644 index f118dcf..0000000 --- a/Spring BFF/resource/repositories/SecurityContextRepository.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.example.timesheetapi.auth.security.repositories - -import org.springframework.context.annotation.Configuration -import org.springframework.security.core.context.SecurityContext -import org.springframework.security.web.server.context.ServerSecurityContextRepository -import org.springframework.web.server.ServerWebExchange -import reactor.core.publisher.Mono - -/**********************************************************************************************************************/ -/***************************************************** REPOSITORY *****************************************************/ -/**********************************************************************************************************************/ - -@Configuration -internal class SecurityContextConfig() : ServerSecurityContextRepository { - - override fun save(exchange: ServerWebExchange, context: SecurityContext): Mono { - return exchange.getSession().doOnNext { session -> - println("Saving SecurityContext: $context in session: ${session.id}") - session.attributes["SPRING_SECURITY_CONTEXT"] = context - }.then() - } - - override fun load(exchange: ServerWebExchange): Mono { - return exchange.getSession().flatMap { session -> - val context = session.attributes["SPRING_SECURITY_CONTEXT"] as? SecurityContext - println("Loading SecurityContext: $context from session: ${session.id}") - Mono.justOrEmpty(context) - } - } - -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file diff --git a/Spring BFF/resource/repositories/SessionRegistryConfig.kt b/Spring BFF/resource/repositories/SessionRegistryConfig.kt deleted file mode 100644 index 05ffa4e..0000000 --- a/Spring BFF/resource/repositories/SessionRegistryConfig.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.example.timesheetapi.auth.security.repositories - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.web.server.session.CookieWebSessionIdResolver -import org.springframework.web.server.session.DefaultWebSessionManager -import org.springframework.web.server.session.InMemoryWebSessionStore -import org.springframework.web.server.session.WebSessionManager - -/**********************************************************************************************************************/ -/***************************************************** REPOSITORY *****************************************************/ -/**********************************************************************************************************************/ - -@Configuration -internal class SessionRegistryConfig() { - - @Bean - fun webSessionManager( -// cookieWebSessionIdResolver: CookieWebSessionIdResolver - ): WebSessionManager { - val sessionManager = DefaultWebSessionManager() - sessionManager.sessionStore = InMemoryWebSessionStore() -// sessionManager.sessionIdResolver = cookieWebSessionIdResolver - return sessionManager - } - -} - -/**********************************************************************************************************************/ -/**************************************************** END OF KOTLIN ***************************************************/ -/**********************************************************************************************************************/ \ No newline at end of file