commit 94cc7ade91a735270fdfc7eee6be72dd56a6b5e5
Author: Petr Urban <urbanp@gapps.zcu.cz>
Date:   Sun Apr 9 23:56:13 2023 +0200

    #10228 - authentication entry point

diff --git a/pom.xml b/pom.xml
index db067b0..4ebd477 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,7 @@
 
 	<dependencies>
 
+
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter</artifactId>
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/JwtAuthenticationFilter.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/JwtAuthenticationFilter.java
index 00ab902..7f77941 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/JwtAuthenticationFilter.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/JwtAuthenticationFilter.java
@@ -6,9 +6,13 @@ import cz.zcu.fav.kiv.antipatterndetectionapp.v2.service.OAuthService;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.service.OAuthServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.annotation.Order;
-import org.springframework.http.ResponseEntity;
+import org.springframework.http.*;
 import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
 import org.springframework.web.filter.OncePerRequestFilter;
 
 import javax.servlet.FilterChain;
@@ -23,33 +27,128 @@ import java.util.Objects;
 @Component
 public class JwtAuthenticationFilter extends OncePerRequestFilter {
 
+    private OAuthService oAuthService;
 
+    public JwtAuthenticationFilter(OAuthService oAuthService) {
+        this.oAuthService = oAuthService;
+    }
+
+//    @Override
+//    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+//        System.out.println("------------------DO FILTER INTERNAL---------------------------");
+//
+//        String authorizationHeader = request.getHeader("Authorization");
+//        if(authorizationHeader == null || authorizationHeader.length() < 7) {
+//            filterChain.doFilter(request, response);
+//            return;
+//        }
+////        OAuthServiceImpl oAuthService = new OAuthServiceImpl();
+//
+//        String token = authorizationHeader.substring(7);
+//
+//        ResponseEntity<String> oAuthResponse =  oAuthService.authenticate(token);
+//        response.setContentType("application/json");
+//        response.setStatus(oAuthResponse.getStatusCodeValue());
+//
+//        BufferedWriter out = new BufferedWriter(response.getWriter());
+//        out.write(Objects.requireNonNull(oAuthResponse.getBody()));
+//        out.flush();
+//        out.close();
+//
+//        filterChain.doFilter(request, response);
+//
+//    }
+
+//    @Override
+//    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+//            throws ServletException, IOException {
+//
+//        String authorizationHeader = request.getHeader("Authorization");
+//        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
+//            String token = authorizationHeader.substring(7);
+//            try {
+//                Authentication authentication = new UsernamePasswordAuthenticationToken(oAuthService.authenticate(token).getBody(), null);
+//                SecurityContextHolder.getContext().setAuthentication(authentication);
+//            } catch (Exception e) {
+//                SecurityContextHolder.clearContext();
+//                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
+//            }
+//        }
+////        String authorizationHeader = request.getHeader("Authorization");
+////
+////        if(authorizationHeader == null || authorizationHeader.length() < 7) {
+////            filterChain.doFilter(request, response);
+////            return;
+////        }
+////
+////        RestTemplate restTemplate = new RestTemplate();
+////        HttpHeaders headers = new HttpHeaders();
+////        headers.setContentType(MediaType.APPLICATION_JSON);
+////
+////
+////        HashMap<String, String> requestBody = new HashMap<>();
+////
+////        requestBody.put("name", "userName");
+////
+////        // set the JWT token in the authorization header
+////
+////        headers.set("Authorization", authorizationHeader);
+////        requestBody.put("token", authorizationHeader.substring(7));
+////        //
+////
+////        String json = JSONBuilder.buildJson(requestBody);
+////
+////        HttpEntity<String> entity = new HttpEntity<>(json, headers);
+////        //RequestBuilder.sendRequestResponse("http://localhost:8081/authenticate",token);
+////        ResponseEntity<String> responseEntity = restTemplate.exchange("http://localhost:8081/authenticate", HttpMethod.POST, entity, String.class);
+////
+////        // do something with the response body
+////
+////        if (responseEntity.getBody().contains("Invalid token")) {
+////            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
+////
+////        } else {
+////            return;
+//////            Authentication authentication = new UsernamePasswordAuthenticationToken("name", null);
+//////            SecurityContextHolder.getContext().setAuthentication(authentication);
+////        }
+////
+//////        filterChain.doFilter(request, response);
+//    }
 
     @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
-        System.out.println("------------------DO FILTER INTERNAL---------------------------");
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
 
         String authorizationHeader = request.getHeader("Authorization");
-        if(authorizationHeader == null || authorizationHeader.length() < 7) {
-            filterChain.doFilter(request, response);
+        if (authorizationHeader == null || authorizationHeader.length() < 7) {
+            chain.doFilter(request, response);
             return;
         }
-        OAuthServiceImpl oAuthService = new OAuthServiceImpl();
-
         String token = authorizationHeader.substring(7);
 
-        ResponseEntity<String> oAuthResponse =  oAuthService.authenticate(token);
-        response.setContentType("application/json");
-        response.setStatus(oAuthResponse.getStatusCodeValue());
-
-        BufferedWriter out = new BufferedWriter(response.getWriter());
-        out.write(Objects.requireNonNull(oAuthResponse.getBody()));
-        out.flush();
-        out.close();
-
-        filterChain.doFilter(request, response);
-
+        ResponseEntity<String> responseEntity = oAuthService.authenticate(token);
+        if (token != null && responseEntity.getBody().contains("OK")) {
+            // Token is valid, proceed with the request
+            chain.doFilter(request, response);
+        } else {
+            // Token is invalid or not present, authenticate the request with external authentication provider
+//            HttpHeaders headers = new HttpHeaders();
+//            headers.setContentType(MediaType.APPLICATION_JSON);
+//            String requestBody = "{\"token\": \"" + token + "\"}";
+//            HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
+//
+//            ResponseEntity<AuthenticationResponse> authenticationResponseEntity =
+//                    restTemplate.postForEntity(AUTHENTICATION_URL, entity, AuthenticationResponse.class);
+//
+//            if (authenticationResponseEntity.getStatusCode() == HttpStatus.OK
+//                    && authenticationResponseEntity.getBody().isAuthenticated()) {
+//                // Request is authenticated, proceed with the request
+//                chain.doFilter(request, response);
+//            } else {
+                // Request is not authenticated, set response status to 401 Unauthorized
+                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+//            }
+        }
     }
-
-
 }
\ No newline at end of file
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/OAuth2ResourceServerConfigurer.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/OAuth2ResourceServerConfigurer.java
new file mode 100644
index 0000000..49936f8
--- /dev/null
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/OAuth2ResourceServerConfigurer.java
@@ -0,0 +1,11 @@
+package cz.zcu.fav.kiv.antipatterndetectionapp.v2.security;
+
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+
+public class OAuth2ResourceServerConfigurer {
+    public static void jwt(
+            org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer<HttpSecurity>
+                    httpSecurityOAuth2ResourceServerConfigurer) {
+
+    }
+}
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/OAuthSecurityHandler.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/OAuthSecurityHandler.java
new file mode 100644
index 0000000..ff87bc4
--- /dev/null
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/OAuthSecurityHandler.java
@@ -0,0 +1,44 @@
+//package cz.zcu.fav.kiv.antipatterndetectionapp.v2.security;
+//
+//
+//import org.springframework.http.ResponseEntity;
+//import org.springframework.security.core.Authentication;
+//import org.springframework.security.oauth2.core.oidc.user.OidcUser;
+//import org.springframework.security.web.authentication.logout.LogoutHandler;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.client.RestTemplate;
+//import org.springframework.web.util.UriComponentsBuilder;
+//
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//
+//@Component
+//public class OAuthSecurityHandler implements LogoutHandler {
+////    private static final Logger logger = LoggerFactory.getLogger(OAuthSecurityHandler.class);
+//    private final RestTemplate restTemplate;
+//
+//    public OAuthSecurityHandler(RestTemplate restTemplate) {
+//        this.restTemplate = restTemplate;
+//    }
+//
+//    @Override
+//    public void logout(HttpServletRequest request, HttpServletResponse response,
+//                       Authentication auth) {
+//        logoutFromKeycloak((OidcUser) auth.getPrincipal());
+//    }
+//
+//    private void logoutFromKeycloak(OidcUser user) {
+//        String endSessionEndpoint = user.getIssuer() + "/protocol/openid-connect/logout";
+//        UriComponentsBuilder builder = UriComponentsBuilder
+//                .fromUriString(endSessionEndpoint)
+//                .queryParam("id_token_hint", user.getIdToken().getTokenValue());
+//
+//        ResponseEntity<String> logoutResponse = restTemplate.getForEntity(
+//                builder.toUriString(), String.class);
+////        if (logoutResponse.getStatusCode().is2xxSuccessful()) {
+////            logger.info("Successfulley logged out from Keycloak");
+////        } else {
+////            logger.error("Could not propagate logout to Keycloak");
+////        }
+//    }
+//}
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/WebSecurityConfig.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/WebSecurityConfig.java
index 30d53c0..c948716 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/WebSecurityConfig.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/WebSecurityConfig.java
@@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
@@ -13,11 +14,12 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.web.authentication.HttpStatusEntryPoint;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.web.client.RestTemplate;
 
 @Configuration
-@EnableWebSecurity
+@EnableWebSecurity(debug = true)
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
     @Autowired
@@ -55,16 +57,20 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
     @Override
     protected void configure(HttpSecurity httpSecurity) throws Exception {
         httpSecurity
-                .csrf()
-                .disable()
+                .csrf().disable()
                 .authorizeRequests()
                 .antMatchers("/v2/user/register", "/v2/user/login").permitAll()
-                .anyRequest()
-                .authenticated()
+                .anyRequest().authenticated()
+                .and()
+                .exceptionHandling()
+                .authenticationEntryPoint(new OAuthServiceImpl())
                 .and()
                 .sessionManagement()
                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
-        httpSecurity.addFilterAfter(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
+//                .and()
+//                .addFilterBefore(new JwtAuthenticationFilter(new OAuthServiceImpl()), UsernamePasswordAuthenticationFilter.class);
+//        httpSecurity.addFilterAfter(new JwtAuthenticationFilter(new OAuthServiceImpl()), UsernamePasswordAuthenticationFilter.class);
+//        httpSecurity.addFilter(new JwtAuthenticationFilter(new OAuthServiceImpl()));
     }
 
 }
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/OAuthServiceImpl.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/OAuthServiceImpl.java
index 621d3a6..d32ebc5 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/OAuthServiceImpl.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/OAuthServiceImpl.java
@@ -32,14 +32,14 @@ public class OAuthServiceImpl implements OAuthService, UserDetailsService {
     /**
      * URL path to authenticate endpoint of OAuth application
      */
-    @Value("${auth.realm.authenticate}")
-    private String AUTH_URL_AUTH;
+//    @Value("${auth.realm.authenticate}")
+    private String AUTH_URL_AUTH = "http://localhost:8081/authenticate";
 
     /**
      * URL path to login endpoint of OAuth application
      */
-    @Value("${auth.realm.login}")
-    private String AUTH_URL_LOGIN;
+//    @Value("${auth.realm.login}")
+    private String AUTH_URL_LOGIN = "http://localhost:8081/login";
 
     /**
      * URL path to logout endpoint of OAuth application
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java
index a992495..747175d 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java
@@ -33,10 +33,11 @@ public class RequestBuilder {
         HttpHeaders headers = new HttpHeaders();
 
         headers.setContentType(MediaType.APPLICATION_JSON);
-        headers.setBearerAuth(token);
+        headers.set("Authorization", "Bearer " + token);
 
         HttpEntity<String> entity = new HttpEntity<>(json, headers);
-        return restTemplate.postForEntity(url, entity, String.class);
+        ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
+        return response;
     }
 
 }
