| 154 | |
| 155 | {{{ |
| 156 | @Bean |
| 157 | public ClientRegistrationRepository clientRegistrationRepository() { |
| 158 | Dotenv dotenv = Dotenv.load(); |
| 159 | String clientId = dotenv.get("GOOGLE_CLIENT_ID"); |
| 160 | String clientSecret = dotenv.get("GOOGLE_CLIENT_SECRET"); |
| 161 | |
| 162 | ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("google") |
| 163 | .clientId(clientId) |
| 164 | .clientSecret(clientSecret) |
| 165 | .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) |
| 166 | .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}") |
| 167 | .scope("openid", "profile", "email") |
| 168 | .authorizationUri("https://accounts.google.com/o/oauth2/auth") |
| 169 | .tokenUri("https://oauth2.googleapis.com/token") |
| 170 | .userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo") |
| 171 | .jwkSetUri("https://www.googleapis.com/oauth2/v3/certs") |
| 172 | .userNameAttributeName("sub") |
| 173 | .clientName("Google") |
| 174 | .build(); |
| 175 | |
| 176 | return new InMemoryClientRegistrationRepository(clientRegistration); |
| 177 | } |
| 178 | }}} |
| 179 | |
| 180 | ** Во овој репозиториум се наоѓа конфигурацијата за земање на api клучевите за google автентикација од .env датотеката. ** |
| 181 | |
| 182 | |
| 183 | {{{ |
| 184 | @Bean |
| 185 | public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
| 186 | http |
| 187 | .csrf(csrf -> csrf.disable()) |
| 188 | .authorizeHttpRequests(auth -> auth |
| 189 | .requestMatchers( |
| 190 | "/api/login", |
| 191 | "/api/register", |
| 192 | "/api/recipes/**", |
| 193 | "/api/favorite", |
| 194 | "/api/favorite/**", |
| 195 | "/api/products", |
| 196 | "/api/users/**", |
| 197 | "/api/reviews", |
| 198 | "/api/usertype", |
| 199 | "/api/productOrders/**", |
| 200 | "/api/orders/**", |
| 201 | "/oauth2/**", |
| 202 | "/login/oauth2/**" |
| 203 | ).permitAll() |
| 204 | .requestMatchers("/api/deliver/**").hasRole("DELIVERYPERSON") |
| 205 | .requestMatchers("/api/admin/**").hasRole("ADMIN") |
| 206 | .anyRequest().authenticated() |
| 207 | ) |
| 208 | .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) |
| 209 | .oauth2Login(oauth2 -> oauth2 |
| 210 | .userInfoEndpoint(userInfo -> userInfo |
| 211 | .userService(customOAuth2UserService) |
| 212 | ) |
| 213 | .successHandler(oAuth2AuthenticationSuccessHandler) |
| 214 | ) |
| 215 | .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); |
| 216 | |
| 217 | return http.build(); |
| 218 | } |
| 219 | }}} |
| 220 | |
| 221 | ** Во овој метод е имплементирано оAuth2 login со customOAuth2UserService сервисот и при успешно најавување се повикува и објектот oAuth2AuthenticationSuccessHandler ** |
| 222 | |
| 223 | {{{ |
| 224 | @Override |
| 225 | public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { |
| 226 | OAuth2User oauth2User = super.loadUser(userRequest); |
| 227 | String email = oauth2User.getAttribute("email"); |
| 228 | String firstName = oauth2User.getAttribute("given_name"); |
| 229 | String lastName = oauth2User.getAttribute("family_name"); |
| 230 | String phoneNumber = oauth2User.getAttribute("phone_number"); |
| 231 | |
| 232 | if (email != null) { |
| 233 | processOAuthPostLogin(email, firstName, lastName, phoneNumber); |
| 234 | |
| 235 | return new DefaultOAuth2User( |
| 236 | Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")), |
| 237 | oauth2User.getAttributes(), |
| 238 | "email" |
| 239 | ); |
| 240 | } else { |
| 241 | throw new OAuth2AuthenticationException("Email not found from OAuth2 provider"); |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | public void processOAuthPostLogin(String email, String firstName, String lastName, String phoneNumber) { |
| 246 | User existingUser = userDAO.findUserByEmail(email).orElse(null); |
| 247 | if (existingUser == null) { |
| 248 | User newUser = new User(); |
| 249 | newUser.setEmail(email); |
| 250 | newUser.setName(firstName != null ? firstName : ""); |
| 251 | newUser.setSurname(lastName != null ? lastName : ""); |
| 252 | newUser.setPhoneNumber(phoneNumber != null ? phoneNumber : ""); |
| 253 | newUser.setPassword(""); |
| 254 | newUser.setUserType(UserType.User); |
| 255 | userDAO.save(newUser); |
| 256 | } |
| 257 | } |
| 258 | }}} |
| 259 | |
| 260 | ** Овој метод се наоѓа во објектот customOAuth2UserService и неговата цел е да ги превземе податоците од Google акаунтот на корисникот и при успешно превземање на мејл адресата се повикува методот processOAuthPostLogin за пронаѓање на корисникот доколку постои, во спротивно се прави зачувување на корисникот во базата. ** |
| 261 | |
| 262 | {{{ |
| 263 | @Override |
| 264 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, |
| 265 | Authentication authentication) throws IOException, ServletException { |
| 266 | if (authentication instanceof OAuth2AuthenticationToken oauth2Token) { |
| 267 | String email = oauth2Token.getPrincipal().getAttribute("email"); |
| 268 | String firstName = oauth2Token.getPrincipal().getAttribute("given_name"); |
| 269 | String lastName = oauth2Token.getPrincipal().getAttribute("family_name"); |
| 270 | String phoneNumber = oauth2Token.getPrincipal().getAttribute("phone_number"); |
| 271 | |
| 272 | if (email != null) { |
| 273 | UserDetails userDetails = userDetailsService.loadUserByUsername(email); |
| 274 | String jwt = jwtUtil.generateToken(userDetails.getUsername()); |
| 275 | |
| 276 | String redirectUrl = String.format( |
| 277 | "http://localhost:3000/loginSuccess?token=%s&firstName=%s&lastName=%s&email=%s&phoneNumber=%s&address=", |
| 278 | jwt, firstName, lastName, email, phoneNumber != null ? phoneNumber : "" |
| 279 | ); |
| 280 | |
| 281 | UriComponents uriComponents = ServletUriComponentsBuilder.fromUriString(redirectUrl).build(); |
| 282 | response.sendRedirect(uriComponents.toUriString()); |
| 283 | } else { |
| 284 | response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Email not found from OAuth2 provider"); |
| 285 | } |
| 286 | } else { |
| 287 | response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Authentication type not supported"); |
| 288 | } |
| 289 | } |
| 290 | }}} |
| 291 | |
| 292 | ** При извршување на овој метод се пренасочува корисникот кон горенаведениот url каде што истовремено се сетира неговиот jwt токен. ** |