├── .gitignore ├── 1-in-memory-auth ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── controller │ │ │ ├── PrivateTestController.java │ │ │ └── PublicTestController.java │ │ │ └── security │ │ │ ├── PasswordEncoderConfig.java │ │ │ └── SecurityConfig.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 10-jwt-very-simple-websocket ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── AuthController.java │ │ │ ├── PrivateTestController.java │ │ │ ├── PublicTestController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ ├── LoginRequest.java │ │ │ ├── RoleDto.java │ │ │ ├── TokenDto.java │ │ │ └── UserDto.java │ │ │ ├── exception │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── mapper │ │ │ ├── RoleMapper.java │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── Authorities.java │ │ │ ├── BaseEntity.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── RoleRepository.java │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── JwtAccessDeniedHandler.java │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ ├── JwtFilter.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ ├── AuthService.java │ │ │ ├── RoleService.java │ │ │ ├── TokenService.java │ │ │ └── UserService.java │ │ │ ├── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ │ │ └── websocket │ │ │ ├── CustomWebSocketHandler.java │ │ │ ├── NotificationsController.java │ │ │ ├── WebSocketConfig.java │ │ │ └── WebSocketSessionService.java │ └── resources │ │ ├── application.yml │ │ └── static │ │ └── index.html │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 2-basic-auth-hardcoded-one-role ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── PrivateTestController.java │ │ │ └── PublicTestController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ └── UserDto.java │ │ │ ├── mapper │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── Authorities.java │ │ │ ├── BaseEntity.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 3-basic-auth-hardcoded-multiple-roles ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── PrivateTestController.java │ │ │ └── PublicTestController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ └── UserDto.java │ │ │ ├── mapper │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── Authorities.java │ │ │ ├── BaseEntity.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 4-basic-auth-dynamic-roles ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── PrivateTestController.java │ │ │ ├── PublicTestController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ ├── RoleDto.java │ │ │ └── UserDto.java │ │ │ ├── mapper │ │ │ ├── RoleMapper.java │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── BaseEntity.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── RoleRepository.java │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ ├── RoleService.java │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 5-basic-auth-role-based-voter ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── PrivateTestController.java │ │ │ ├── PublicTestController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ ├── RestrictedEndpoint.java │ │ │ ├── RoleDto.java │ │ │ └── UserDto.java │ │ │ ├── mapper │ │ │ ├── RoleMapper.java │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── BaseEntity.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── RoleRepository.java │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── RoleBasedVoter.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ ├── RoleService.java │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 6-jwt-very-simple ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── AuthController.java │ │ │ ├── PrivateTestController.java │ │ │ ├── PublicTestController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ ├── LoginRequest.java │ │ │ ├── RoleDto.java │ │ │ ├── TokenDto.java │ │ │ └── UserDto.java │ │ │ ├── exception │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── mapper │ │ │ ├── RoleMapper.java │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── Authorities.java │ │ │ ├── BaseEntity.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── RoleRepository.java │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── JwtAccessDeniedHandler.java │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ ├── JwtFilter.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ ├── AuthService.java │ │ │ ├── RoleService.java │ │ │ ├── TokenService.java │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 7-jwt-with-refresh-token ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── AuthController.java │ │ │ ├── PrivateTestController.java │ │ │ ├── PublicTestController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ ├── LoginRequest.java │ │ │ ├── RefreshTokenRequest.java │ │ │ ├── RoleDto.java │ │ │ ├── TokenDto.java │ │ │ └── UserDto.java │ │ │ ├── exception │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── mapper │ │ │ ├── RoleMapper.java │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── Authorities.java │ │ │ ├── BaseEntity.java │ │ │ ├── Role.java │ │ │ ├── Token.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── RoleRepository.java │ │ │ ├── TokenRepository.java │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── JwtAccessDeniedHandler.java │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ ├── JwtFilter.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ ├── AuthService.java │ │ │ ├── RoleService.java │ │ │ ├── TokenService.java │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 8-jwt-and-otp ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── AuthController.java │ │ │ ├── HomeController.java │ │ │ ├── PrivateTestController.java │ │ │ ├── PublicTestController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ ├── LoginRequest.java │ │ │ ├── PasswordForgetRequest.java │ │ │ ├── RefreshTokenRequest.java │ │ │ ├── RoleDto.java │ │ │ ├── SetNewPasswordRequest.java │ │ │ ├── TokenDto.java │ │ │ └── UserDto.java │ │ │ ├── event │ │ │ ├── UserRegisterEvent.java │ │ │ └── listener │ │ │ │ └── UserRegisterEventListener.java │ │ │ ├── exception │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── mapper │ │ │ ├── RoleMapper.java │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── Authorities.java │ │ │ ├── BaseEntity.java │ │ │ ├── OTP.java │ │ │ ├── OTPType.java │ │ │ ├── Role.java │ │ │ ├── Token.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── OTPRepository.java │ │ │ ├── RoleRepository.java │ │ │ ├── TokenRepository.java │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomUserDetails.java │ │ │ ├── JwtAccessDeniedHandler.java │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ ├── JwtFilter.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── service │ │ │ ├── AuthService.java │ │ │ ├── OTPService.java │ │ │ ├── RoleService.java │ │ │ ├── TokenService.java │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ ├── application.yml │ │ └── templates │ │ ├── activationError.html │ │ ├── activationSuccess.html │ │ ├── index.html │ │ └── resetPassword.html │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── 9-jwt-and-oauth2-social-login ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── gucardev │ │ │ └── springsecurityexamples │ │ │ ├── ServletInitializer.java │ │ │ ├── SpringSecurityExamplesApplication.java │ │ │ ├── Startup.java │ │ │ ├── controller │ │ │ ├── AuthController.java │ │ │ ├── HomeController.java │ │ │ ├── PrivateTestController.java │ │ │ ├── PublicTestController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── BaseDto.java │ │ │ ├── LoginRequest.java │ │ │ ├── PasswordForgetRequest.java │ │ │ ├── RefreshTokenRequest.java │ │ │ ├── RoleDto.java │ │ │ ├── SetNewPasswordRequest.java │ │ │ ├── TokenDto.java │ │ │ └── UserDto.java │ │ │ ├── event │ │ │ ├── UserRegisterEvent.java │ │ │ └── listener │ │ │ │ └── UserRegisterEventListener.java │ │ │ ├── exception │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── mapper │ │ │ ├── RoleMapper.java │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ ├── Authorities.java │ │ │ ├── BaseEntity.java │ │ │ ├── OAuth2Provider.java │ │ │ ├── OTP.java │ │ │ ├── OTPType.java │ │ │ ├── Role.java │ │ │ ├── Token.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── OTPRepository.java │ │ │ ├── RoleRepository.java │ │ │ ├── TokenRepository.java │ │ │ └── UserRepository.java │ │ │ ├── security │ │ │ ├── CustomOauthUserDetails.java │ │ │ ├── CustomUserDetails.java │ │ │ ├── JwtAccessDeniedHandler.java │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ ├── JwtFilter.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ ├── UserDetailsServiceImpl.java │ │ │ └── oauth │ │ │ │ ├── CustomAuthenticationSuccessHandler.java │ │ │ │ ├── CustomOAuth2UserService.java │ │ │ │ ├── GitHubOAuth2UserInfoExtractor.java │ │ │ │ ├── GoogleOAuth2UserInfoExtractor.java │ │ │ │ └── OAuth2UserInfoExtractor.java │ │ │ ├── service │ │ │ ├── AuthService.java │ │ │ ├── OTPService.java │ │ │ ├── RoleService.java │ │ │ ├── TokenService.java │ │ │ └── UserService.java │ │ │ └── validation │ │ │ ├── CreateValidationGroup.java │ │ │ └── UpdateValidationGroup.java │ └── resources │ │ ├── application.yml │ │ └── templates │ │ ├── activationError.html │ │ ├── activationSuccess.html │ │ ├── callBack.html │ │ ├── index.html │ │ └── resetPassword.html │ └── test │ └── java │ └── com │ └── gucardev │ └── springsecurityexamples │ └── SpringSecurityExamplesApplicationTests.java ├── README.md └── spring-security.postman_collection.json /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /1-in-memory-auth/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /1-in-memory-auth/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/1-in-memory-auth/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /1-in-memory-auth/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /1-in-memory-auth/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /1-in-memory-auth/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | // @SpringBootApplication(exclude = {SecurityAutoConfiguration.class}) 7 | @SpringBootApplication 8 | public class SpringSecurityExamplesApplication { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /1-in-memory-auth/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | // @PreAuthorize("hasRole('ROLE_ADMIN')") // need ROLE_ prefix 19 | @PreAuthorize("hasAuthority('create')") 20 | @GetMapping("/admin") 21 | public ResponseEntity sayHelloToAdmin() { 22 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 23 | } 24 | 25 | @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')") 26 | @GetMapping("/user") 27 | public ResponseEntity sayHelloToUser() { 28 | return ResponseEntity.ok("Hello User! This is private endpoint"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /1-in-memory-auth/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /1-in-memory-auth/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /1-in-memory-auth/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | # 10 | -------------------------------------------------------------------------------- /1-in-memory-auth/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/10-jwt-very-simple-websocket/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | @SpringBootApplication 8 | @EnableJpaAuditing 9 | public class SpringSecurityExamplesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/controller/AuthController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.LoginRequest; 4 | import com.gucardev.springsecurityexamples.dto.TokenDto; 5 | import com.gucardev.springsecurityexamples.service.AuthService; 6 | import jakarta.validation.Valid; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @RestController 15 | @RequestMapping("/auth") 16 | @RequiredArgsConstructor 17 | public class AuthController { 18 | 19 | private final AuthService authService; 20 | 21 | @PostMapping("/login") 22 | public ResponseEntity login(@Valid @RequestBody LoginRequest loginRequest) { 23 | return ResponseEntity.ok().body(authService.login(loginRequest)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | @PreAuthorize("hasAuthority('ADMIN')") 19 | @GetMapping("/admin") 20 | public ResponseEntity sayHelloToAdmin() { 21 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 22 | } 23 | 24 | @PreAuthorize("hasAnyAuthority('ADMIN','USER')") 25 | @GetMapping("/user") 26 | public ResponseEntity sayHelloToUser() { 27 | return ResponseEntity.ok("Hello User! This is private endpoint"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.service.RoleService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/role") 10 | public class RoleController { 11 | 12 | private final RoleService roleService; 13 | 14 | public RoleController(RoleService roleService) { 15 | this.roleService = roleService; 16 | } 17 | 18 | @GetMapping 19 | public List getRoles() { 20 | return roleService.getRoles(); 21 | } 22 | 23 | @PostMapping 24 | public RoleDto createRole(@RequestBody RoleDto userDto) { 25 | return roleService.createRole(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/users") 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | public UserController(UserService userService) { 15 | this.userService = userService; 16 | } 17 | 18 | @GetMapping 19 | public List getUsers() { 20 | return userService.getUsers(); 21 | } 22 | 23 | @PostMapping 24 | public UserDto createUser(@RequestBody UserDto userDto) { 25 | return userService.createUser(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/dto/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LoginRequest { 8 | @NotBlank private String username; 9 | @NotBlank private String password; 10 | } 11 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | 11 | @Getter 12 | @Setter 13 | public class RoleDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | } 21 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/dto/TokenDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class TokenDto { 13 | private String accessToken; 14 | private UserDto user; 15 | } 16 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import java.util.Set; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | public class UserDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | 21 | private String username; 22 | 23 | @NotNull(groups = {CreateValidationGroup.class}) 24 | @Null(groups = {UpdateValidationGroup.class}) 25 | private String password; 26 | 27 | private boolean isEnabled; 28 | 29 | private Set roles; 30 | } 31 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import org.mapstruct.BeanMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.MappingTarget; 8 | import org.mapstruct.NullValuePropertyMappingStrategy; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface RoleMapper { 12 | 13 | RoleDto toDto(Role role); 14 | 15 | Role toEntity(RoleDto role); 16 | 17 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 18 | void updatePartial(@MappingTarget Role entity, RoleDto dto); 19 | } 20 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/model/Authorities.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public class Authorities {} 4 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | @Entity 12 | @Table(name = "ROLES") 13 | @Getter 14 | @Setter 15 | public class Role extends BaseEntity implements GrantedAuthority { 16 | 17 | @Column(name = "role_name") 18 | private String name; 19 | 20 | @ManyToMany( 21 | fetch = FetchType.LAZY, 22 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 23 | mappedBy = "roles") 24 | @JsonIgnore 25 | private Set users = new HashSet<>(); 26 | 27 | @Override 28 | public String getAuthority() { 29 | return getName(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Collection; 5 | import java.util.Set; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | 11 | 12 | @Entity 13 | @Table(name = "USERS") 14 | @Getter 15 | @Setter 16 | public class User extends BaseEntity { 17 | 18 | @Column(nullable = false) 19 | private String name; 20 | 21 | @Column(nullable = false) 22 | private String username; 23 | 24 | @Column(nullable = false) 25 | private String password; 26 | 27 | private boolean isEnabled; 28 | 29 | @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) 30 | @JoinTable( 31 | name = "user_role", 32 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 33 | inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) 34 | private Set roles; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface RoleRepository extends JpaRepository {} 9 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | } 13 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/security/JwtAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.security.web.access.AccessDeniedHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAccessDeniedHandler implements AccessDeniedHandler { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void handle( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AccessDeniedException accessDeniedException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString( 31 | Map.of("error", accessDeniedException.getLocalizedMessage()))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void commence( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AuthenticationException authException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString(Map.of("error", authException.getLocalizedMessage()))); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @RequiredArgsConstructor 12 | public class UserDetailsServiceImpl implements UserDetailsService { 13 | 14 | private final UserService userService; 15 | 16 | @Override 17 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 18 | return new CustomUserDetails(userService.getByUsername(username)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/service/AuthService.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.service; 2 | 3 | import com.gucardev.springsecurityexamples.dto.LoginRequest; 4 | import com.gucardev.springsecurityexamples.dto.TokenDto; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | @Slf4j 13 | @RequiredArgsConstructor 14 | public class AuthService { 15 | 16 | private final TokenService tokenService; 17 | private final AuthenticationManager authenticationManager; 18 | 19 | public TokenDto login(LoginRequest loginRequest) { 20 | try { 21 | authenticationManager.authenticate( 22 | new UsernamePasswordAuthenticationToken( 23 | loginRequest.getUsername(), loginRequest.getPassword())); 24 | return tokenService.generateTokenPairs(loginRequest.getUsername()); 25 | } catch (Exception e) { 26 | throw new RuntimeException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/websocket/NotificationsController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.websocket; 2 | 3 | import java.io.IOException; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RestController; 9 | import org.springframework.web.socket.TextMessage; 10 | 11 | @RestController 12 | @RequiredArgsConstructor 13 | public class NotificationsController { 14 | private final WebSocketSessionService sessionService; 15 | 16 | @PostMapping("/notifications/{user}") 17 | public void createNotification(@PathVariable String user, @RequestBody String notification) 18 | throws IOException { 19 | if (notification == null) { 20 | throw new IllegalArgumentException("Notification should not be null"); 21 | } 22 | 23 | var session = sessionService.getSession(user); 24 | if (session == null) { 25 | throw new IllegalStateException(user + " is not connected"); 26 | } 27 | 28 | session.sendMessage(new TextMessage(notification)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/websocket/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.websocket; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 5 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 6 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 7 | 8 | @Configuration 9 | @EnableWebSocket 10 | public class WebSocketConfig implements WebSocketConfigurer { 11 | private final WebSocketSessionService sessionService; 12 | 13 | public WebSocketConfig(WebSocketSessionService sessionService) { 14 | this.sessionService = sessionService; 15 | } 16 | 17 | @Override 18 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 19 | registry.addHandler(new CustomWebSocketHandler(sessionService), "/ws") 20 | .setAllowedOriginPatterns("*"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/java/com/gucardev/springsecurityexamples/websocket/WebSocketSessionService.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.websocket; 2 | 3 | import org.springframework.stereotype.Service; 4 | import org.springframework.web.socket.WebSocketSession; 5 | 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | @Service 9 | public class WebSocketSessionService { 10 | 11 | private final ConcurrentHashMap sessions = new ConcurrentHashMap<>(); 12 | 13 | public void addSession(String user, WebSocketSession session) { 14 | sessions.put(user, session); 15 | } 16 | 17 | public void removeSession(String user) { 18 | sessions.remove(user); 19 | } 20 | 21 | public WebSocketSession getSession(String user) { 22 | return sessions.get(user); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | spring: 11 | h2: 12 | console: 13 | enabled: true 14 | datasource: 15 | url: jdbc:h2:mem:db 16 | jpa: 17 | hibernate: 18 | ddl-auto: create 19 | 20 | jwt-variables: 21 | EXPIRES_ACCESS_TOKEN_MINUTE: 1 22 | ISSUER: dev 23 | KEY: asdqwe123+K3Y -------------------------------------------------------------------------------- /10-jwt-very-simple-websocket/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/2-basic-auth-hardcoded-one-role/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | // @SpringBootApplication(exclude = {SecurityAutoConfiguration.class}) 8 | @SpringBootApplication 9 | @EnableJpaAuditing 10 | public class SpringSecurityExamplesApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | package com.gucardev.springsecurityexamples.controller; 6 | 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | @RequestMapping("/private") 15 | public class PrivateTestController { 16 | 17 | @GetMapping 18 | public ResponseEntity sayHelloToAnyAuthenticated() { 19 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 20 | } 21 | 22 | @PreAuthorize("hasRole('ROLE_ADMIN')") 23 | @GetMapping("/admin") 24 | public ResponseEntity sayHelloToAdmin() { 25 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 26 | } 27 | 28 | @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')") 29 | @GetMapping("/user") 30 | public ResponseEntity sayHelloToUser() { 31 | return ResponseEntity.ok("Hello User! This is private endpoint"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 5 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 6 | import jakarta.validation.constraints.NotNull; 7 | import jakarta.validation.constraints.Null; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | public class UserDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | 21 | private String username; 22 | 23 | @NotNull(groups = {CreateValidationGroup.class}) 24 | @Null(groups = {UpdateValidationGroup.class}) 25 | private String password; 26 | 27 | private boolean isEnabled; 28 | 29 | private Role role; 30 | } 31 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/model/Authorities.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public class Authorities {} 4 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | 5 | public enum Role implements GrantedAuthority { 6 | ROLE_ADMIN, 7 | ROLE_USER, 8 | ROLE_MOD; 9 | 10 | @Override 11 | public String getAuthority() { 12 | return name(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Entity 8 | @Table(name = "USERS") 9 | @Getter 10 | @Setter 11 | public class User extends BaseEntity { 12 | 13 | @Column(nullable = false) 14 | private String name; 15 | 16 | @Column(nullable = false) 17 | private String username; 18 | 19 | @Column(nullable = false) 20 | private String password; 21 | 22 | private boolean isEnabled; 23 | 24 | @Column(name = "role", nullable = false) 25 | @Enumerated(EnumType.STRING) 26 | private Role role; 27 | } 28 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | } 13 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import jakarta.persistence.EntityNotFoundException; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | @RequiredArgsConstructor 13 | public class UserDetailsServiceImpl implements UserDetailsService { 14 | 15 | private final UserService userService; 16 | 17 | @Override 18 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 19 | var user = userService.getByUsername(username); 20 | if (user.isEmpty()) { 21 | throw new EntityNotFoundException(); 22 | } 23 | return new CustomUserDetails(user.get()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | 11 | 12 | spring: 13 | h2: 14 | console: 15 | enabled: true 16 | datasource: 17 | url: jdbc:h2:mem:db 18 | jpa: 19 | hibernate: 20 | ddl-auto: create 21 | -------------------------------------------------------------------------------- /2-basic-auth-hardcoded-one-role/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/3-basic-auth-hardcoded-multiple-roles/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | // @SpringBootApplication(exclude = {SecurityAutoConfiguration.class}) 8 | @SpringBootApplication 9 | @EnableJpaAuditing 10 | public class SpringSecurityExamplesApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | package com.gucardev.springsecurityexamples.controller; 6 | 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | @RequestMapping("/private") 15 | public class PrivateTestController { 16 | 17 | @GetMapping 18 | public ResponseEntity sayHelloToAnyAuthenticated() { 19 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 20 | } 21 | 22 | @PreAuthorize("hasRole('ROLE_ADMIN')") 23 | @GetMapping("/admin") 24 | public ResponseEntity sayHelloToAdmin() { 25 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 26 | } 27 | 28 | @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')") 29 | @GetMapping("/user") 30 | public ResponseEntity sayHelloToUser() { 31 | return ResponseEntity.ok("Hello User! This is private endpoint"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 5 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 6 | import jakarta.validation.constraints.NotNull; 7 | import jakarta.validation.constraints.Null; 8 | import java.util.Set; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Getter 13 | @Setter 14 | public class UserDto extends BaseDto { 15 | 16 | @Null(groups = {CreateValidationGroup.class}) 17 | @NotNull(groups = {UpdateValidationGroup.class}) 18 | private Long id; 19 | 20 | private String name; 21 | 22 | private String username; 23 | 24 | @NotNull(groups = {CreateValidationGroup.class}) 25 | @Null(groups = {UpdateValidationGroup.class}) 26 | private String password; 27 | 28 | private boolean isEnabled; 29 | 30 | private Set roles; 31 | } 32 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import com.gucardev.springsecurityexamples.model.User; 6 | import org.mapstruct.*; 7 | import org.springframework.security.core.GrantedAuthority; 8 | 9 | @Mapper(componentModel = "spring") 10 | public interface UserMapper { 11 | 12 | UserDto toDto(User entity); 13 | 14 | default Role map(GrantedAuthority authority) { 15 | return Role.valueOf(authority.getAuthority()); 16 | } 17 | 18 | User toEntity(UserDto entity); 19 | 20 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 21 | void updatePartial(@MappingTarget User entity, UserDto dto); 22 | } 23 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/model/Authorities.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public class Authorities {} 4 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | 5 | public enum Role implements GrantedAuthority { 6 | ROLE_ADMIN, 7 | ROLE_USER, 8 | ROLE_MOD; 9 | 10 | @Override 11 | public String getAuthority() { 12 | return name(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Set; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Entity 9 | @Table(name = "USERS") 10 | @Getter 11 | @Setter 12 | public class User extends BaseEntity { 13 | 14 | @Column(nullable = false) 15 | private String name; 16 | 17 | @Column(nullable = false) 18 | private String username; 19 | 20 | @Column(nullable = false) 21 | private String password; 22 | 23 | private boolean isEnabled; 24 | 25 | @ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER) 26 | @JoinTable(name = "authorities", joinColumns = @JoinColumn(name = "user_id")) 27 | @Column(name = "role", nullable = false) 28 | @Enumerated(EnumType.STRING) 29 | private Set roles; 30 | } 31 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | } 13 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/security/CustomUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Collection; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | public class CustomUserDetails implements UserDetails { 9 | 10 | private final User user; 11 | 12 | public CustomUserDetails(User user) { 13 | this.user = user; 14 | } 15 | 16 | @Override 17 | public Collection getAuthorities() { 18 | return this.user.getRoles(); 19 | } 20 | 21 | @Override 22 | public String getPassword() { 23 | return this.user.getPassword(); 24 | } 25 | 26 | @Override 27 | public String getUsername() { 28 | return this.user.getUsername(); 29 | } 30 | 31 | @Override 32 | public boolean isAccountNonExpired() { 33 | return true; 34 | } 35 | 36 | @Override 37 | public boolean isAccountNonLocked() { 38 | return true; 39 | } 40 | 41 | @Override 42 | public boolean isCredentialsNonExpired() { 43 | return true; 44 | } 45 | 46 | @Override 47 | public boolean isEnabled() { 48 | return this.user.isEnabled(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import jakarta.persistence.EntityNotFoundException; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | @RequiredArgsConstructor 13 | public class UserDetailsServiceImpl implements UserDetailsService { 14 | 15 | private final UserService userService; 16 | 17 | @Override 18 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 19 | var user = userService.getByUsername(username); 20 | if (user.isEmpty()) { 21 | throw new EntityNotFoundException(); 22 | } 23 | return new CustomUserDetails(user.get()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | 11 | 12 | spring: 13 | h2: 14 | console: 15 | enabled: true 16 | datasource: 17 | url: jdbc:h2:mem:db 18 | jpa: 19 | hibernate: 20 | ddl-auto: create 21 | -------------------------------------------------------------------------------- /3-basic-auth-hardcoded-multiple-roles/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/4-basic-auth-dynamic-roles/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | @SpringBootApplication 8 | @EnableJpaAuditing 9 | public class SpringSecurityExamplesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | @PreAuthorize("hasAuthority('ADMIN')") 19 | @GetMapping("/admin") 20 | public ResponseEntity sayHelloToAdmin() { 21 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 22 | } 23 | 24 | @PreAuthorize("hasAnyAuthority('ADMIN','USER')") 25 | @GetMapping("/user") 26 | public ResponseEntity sayHelloToUser() { 27 | return ResponseEntity.ok("Hello User! This is private endpoint"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.service.RoleService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/role") 10 | public class RoleController { 11 | 12 | private final RoleService roleService; 13 | 14 | public RoleController(RoleService roleService) { 15 | this.roleService = roleService; 16 | } 17 | 18 | @GetMapping 19 | public List getRoles() { 20 | return roleService.getRoles(); 21 | } 22 | 23 | @PostMapping 24 | public RoleDto createRole(@RequestBody RoleDto userDto) { 25 | return roleService.createRole(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/users") 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | public UserController(UserService userService) { 15 | this.userService = userService; 16 | } 17 | 18 | @GetMapping 19 | public List getUsers() { 20 | return userService.getUsers(); 21 | } 22 | 23 | @PostMapping 24 | public UserDto createUser(@RequestBody UserDto userDto) { 25 | return userService.createUser(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @Getter 11 | @Setter 12 | public class RoleDto extends BaseDto { 13 | 14 | @Null(groups = {CreateValidationGroup.class}) 15 | @NotNull(groups = {UpdateValidationGroup.class}) 16 | private Long id; 17 | 18 | private String name; 19 | } 20 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.persistence.*; 6 | import jakarta.validation.constraints.NotNull; 7 | import jakarta.validation.constraints.Null; 8 | import java.util.Set; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Getter 13 | @Setter 14 | public class UserDto extends BaseDto { 15 | 16 | @Null(groups = {CreateValidationGroup.class}) 17 | @NotNull(groups = {UpdateValidationGroup.class}) 18 | private Long id; 19 | 20 | private String name; 21 | 22 | private String username; 23 | 24 | @NotNull(groups = {CreateValidationGroup.class}) 25 | @Null(groups = {UpdateValidationGroup.class}) 26 | private String password; 27 | 28 | private boolean isEnabled; 29 | 30 | private Set roles; 31 | } 32 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import org.mapstruct.BeanMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.MappingTarget; 8 | import org.mapstruct.NullValuePropertyMappingStrategy; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface RoleMapper { 12 | 13 | RoleDto toDto(Role role); 14 | 15 | Role toEntity(RoleDto role); 16 | 17 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 18 | void updatePartial(@MappingTarget Role entity, RoleDto dto); 19 | } 20 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | @Entity 12 | @Table(name = "ROLES") 13 | @Getter 14 | @Setter 15 | public class Role extends BaseEntity implements GrantedAuthority { 16 | 17 | @Column(name = "role_name") 18 | private String name; 19 | 20 | @ManyToMany( 21 | fetch = FetchType.LAZY, 22 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 23 | mappedBy = "roles") 24 | @JsonIgnore 25 | private Set users = new HashSet<>(); 26 | 27 | @Override 28 | public String getAuthority() { 29 | return getName(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Set; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Entity 9 | @Table(name = "USERS") 10 | @Getter 11 | @Setter 12 | public class User extends BaseEntity { 13 | 14 | @Column(nullable = false) 15 | private String name; 16 | 17 | @Column(nullable = false) 18 | private String username; 19 | 20 | @Column(nullable = false) 21 | private String password; 22 | 23 | private boolean isEnabled; 24 | 25 | @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) 26 | @JoinTable( 27 | name = "user_role", 28 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 29 | inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) 30 | private Set roles; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface RoleRepository extends JpaRepository {} 9 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | } 13 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/security/CustomUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Collection; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | public class CustomUserDetails implements UserDetails { 9 | 10 | private final User user; 11 | 12 | public CustomUserDetails(User user) { 13 | this.user = user; 14 | } 15 | 16 | @Override 17 | public Collection getAuthorities() { 18 | return this.user.getRoles(); 19 | } 20 | 21 | @Override 22 | public String getPassword() { 23 | return this.user.getPassword(); 24 | } 25 | 26 | @Override 27 | public String getUsername() { 28 | return this.user.getUsername(); 29 | } 30 | 31 | @Override 32 | public boolean isAccountNonExpired() { 33 | return true; 34 | } 35 | 36 | @Override 37 | public boolean isAccountNonLocked() { 38 | return true; 39 | } 40 | 41 | @Override 42 | public boolean isCredentialsNonExpired() { 43 | return true; 44 | } 45 | 46 | @Override 47 | public boolean isEnabled() { 48 | return this.user.isEnabled(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import jakarta.persistence.EntityNotFoundException; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | @RequiredArgsConstructor 13 | public class UserDetailsServiceImpl implements UserDetailsService { 14 | 15 | private final UserService userService; 16 | 17 | @Override 18 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 19 | var user = userService.getByUsername(username); 20 | if (user.isEmpty()) { 21 | throw new EntityNotFoundException(); 22 | } 23 | return new CustomUserDetails(user.get()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | 11 | 12 | spring: 13 | h2: 14 | console: 15 | enabled: true 16 | datasource: 17 | url: jdbc:h2:mem:db 18 | jpa: 19 | hibernate: 20 | ddl-auto: create 21 | 22 | -------------------------------------------------------------------------------- /4-basic-auth-dynamic-roles/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/5-basic-auth-role-based-voter/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | @SpringBootApplication 8 | @EnableJpaAuditing 9 | public class SpringSecurityExamplesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | @PreAuthorize("hasAuthority('ADMIN')") 19 | @GetMapping("/admin") 20 | public ResponseEntity sayHelloToAdmin() { 21 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 22 | } 23 | 24 | @PreAuthorize("hasAnyAuthority('ADMIN','USER')") 25 | @GetMapping("/user") 26 | public ResponseEntity sayHelloToUser() { 27 | return ResponseEntity.ok("Hello User! This is private endpoint"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/users") 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | public UserController(UserService userService) { 15 | this.userService = userService; 16 | } 17 | 18 | @GetMapping 19 | public List getUsers() { 20 | return userService.getUsers(); 21 | } 22 | 23 | @PostMapping 24 | public UserDto createUser(@RequestBody UserDto userDto) { 25 | return userService.createUser(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/dto/RestrictedEndpoint.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class RestrictedEndpoint { 9 | 10 | private Long roleId; 11 | private String endpoint; 12 | } 13 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import java.util.Set; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | public class RoleDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | 21 | private Set restrictedEndpoints; 22 | } 23 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.persistence.*; 6 | import jakarta.validation.constraints.NotNull; 7 | import jakarta.validation.constraints.Null; 8 | import java.util.Set; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Getter 13 | @Setter 14 | public class UserDto extends BaseDto { 15 | 16 | @Null(groups = {CreateValidationGroup.class}) 17 | @NotNull(groups = {UpdateValidationGroup.class}) 18 | private Long id; 19 | 20 | private String name; 21 | 22 | private String username; 23 | 24 | @NotNull(groups = {CreateValidationGroup.class}) 25 | @Null(groups = {UpdateValidationGroup.class}) 26 | private String password; 27 | 28 | private boolean isEnabled; 29 | 30 | private Set roles; 31 | } 32 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import org.mapstruct.BeanMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.MappingTarget; 8 | import org.mapstruct.NullValuePropertyMappingStrategy; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface RoleMapper { 12 | 13 | RoleDto toDto(Role role); 14 | 15 | Role toEntity(RoleDto role); 16 | 17 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 18 | void updatePartial(@MappingTarget Role entity, RoleDto dto); 19 | } 20 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | @Entity 12 | @Table(name = "ROLES") 13 | @Getter 14 | @Setter 15 | public class Role extends BaseEntity implements GrantedAuthority { 16 | 17 | @Column(name = "role_name") 18 | private String name; 19 | 20 | @ElementCollection(fetch = FetchType.EAGER) 21 | @CollectionTable(name = "role_endpoints", joinColumns = @JoinColumn(name = "role_id")) 22 | @Column(name = "restricted_endpoint") 23 | private Set restrictedEndpoints = new HashSet<>(); 24 | 25 | @ManyToMany( 26 | fetch = FetchType.LAZY, 27 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 28 | mappedBy = "roles") 29 | @JsonIgnore 30 | private Set users = new HashSet<>(); 31 | 32 | @Override 33 | public String getAuthority() { 34 | return getName(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Set; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | 9 | @Entity 10 | @Table(name = "USERS") 11 | @Getter 12 | @Setter 13 | public class User extends BaseEntity { 14 | 15 | @Column(nullable = false) 16 | private String name; 17 | 18 | @Column(nullable = false) 19 | private String username; 20 | 21 | @Column(nullable = false) 22 | private String password; 23 | 24 | private boolean isEnabled; 25 | 26 | @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) 27 | @JoinTable( 28 | name = "user_role", 29 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 30 | inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) 31 | private Set roles; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import java.util.List; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface RoleRepository extends JpaRepository { 10 | 11 | List findByUsers_Username(String username); 12 | } 13 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | } 13 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import jakarta.persistence.EntityNotFoundException; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.stereotype.Service; 11 | @Service 12 | @RequiredArgsConstructor 13 | public class UserDetailsServiceImpl implements UserDetailsService { 14 | 15 | private final UserService userService; 16 | 17 | @Override 18 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 19 | var user = userService.getByUsername(username); 20 | if (user.isEmpty()) { 21 | throw new EntityNotFoundException(); 22 | } 23 | return new CustomUserDetails(user.get()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | 11 | 12 | spring: 13 | h2: 14 | console: 15 | enabled: true 16 | datasource: 17 | url: jdbc:h2:mem:db 18 | jpa: 19 | hibernate: 20 | ddl-auto: create 21 | 22 | -------------------------------------------------------------------------------- /5-basic-auth-role-based-voter/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /6-jwt-very-simple/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /6-jwt-very-simple/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/6-jwt-very-simple/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /6-jwt-very-simple/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | @SpringBootApplication 8 | @EnableJpaAuditing 9 | public class SpringSecurityExamplesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/controller/AuthController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.LoginRequest; 4 | import com.gucardev.springsecurityexamples.dto.TokenDto; 5 | import com.gucardev.springsecurityexamples.service.AuthService; 6 | import jakarta.validation.Valid; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @RestController 15 | @RequestMapping("/auth") 16 | @RequiredArgsConstructor 17 | public class AuthController { 18 | 19 | private final AuthService authService; 20 | 21 | @PostMapping("/login") 22 | public ResponseEntity login(@Valid @RequestBody LoginRequest loginRequest) { 23 | return ResponseEntity.ok().body(authService.login(loginRequest)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | @PreAuthorize("hasAuthority('ADMIN')") 19 | @GetMapping("/admin") 20 | public ResponseEntity sayHelloToAdmin() { 21 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 22 | } 23 | 24 | @PreAuthorize("hasAnyAuthority('ADMIN','USER')") 25 | @GetMapping("/user") 26 | public ResponseEntity sayHelloToUser() { 27 | return ResponseEntity.ok("Hello User! This is private endpoint"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.service.RoleService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/role") 10 | public class RoleController { 11 | 12 | private final RoleService roleService; 13 | 14 | public RoleController(RoleService roleService) { 15 | this.roleService = roleService; 16 | } 17 | 18 | @GetMapping 19 | public List getRoles() { 20 | return roleService.getRoles(); 21 | } 22 | 23 | @PostMapping 24 | public RoleDto createRole(@RequestBody RoleDto userDto) { 25 | return roleService.createRole(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/users") 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | public UserController(UserService userService) { 15 | this.userService = userService; 16 | } 17 | 18 | @GetMapping 19 | public List getUsers() { 20 | return userService.getUsers(); 21 | } 22 | 23 | @PostMapping 24 | public UserDto createUser(@RequestBody UserDto userDto) { 25 | return userService.createUser(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/dto/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LoginRequest { 8 | @NotBlank private String username; 9 | @NotBlank private String password; 10 | } 11 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | 11 | @Getter 12 | @Setter 13 | public class RoleDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | } 21 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/dto/TokenDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class TokenDto { 13 | private String accessToken; 14 | private UserDto user; 15 | } 16 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import java.util.Set; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | public class UserDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | 21 | private String username; 22 | 23 | @NotNull(groups = {CreateValidationGroup.class}) 24 | @Null(groups = {UpdateValidationGroup.class}) 25 | private String password; 26 | 27 | private boolean isEnabled; 28 | 29 | private Set roles; 30 | } 31 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import org.mapstruct.BeanMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.MappingTarget; 8 | import org.mapstruct.NullValuePropertyMappingStrategy; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface RoleMapper { 12 | 13 | RoleDto toDto(Role role); 14 | 15 | Role toEntity(RoleDto role); 16 | 17 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 18 | void updatePartial(@MappingTarget Role entity, RoleDto dto); 19 | } 20 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/model/Authorities.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public class Authorities {} 4 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | @Entity 12 | @Table(name = "ROLES") 13 | @Getter 14 | @Setter 15 | public class Role extends BaseEntity implements GrantedAuthority { 16 | 17 | @Column(name = "role_name") 18 | private String name; 19 | 20 | @ManyToMany( 21 | fetch = FetchType.LAZY, 22 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 23 | mappedBy = "roles") 24 | @JsonIgnore 25 | private Set users = new HashSet<>(); 26 | 27 | @Override 28 | public String getAuthority() { 29 | return getName(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Collection; 5 | import java.util.Set; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | 11 | 12 | @Entity 13 | @Table(name = "USERS") 14 | @Getter 15 | @Setter 16 | public class User extends BaseEntity { 17 | 18 | @Column(nullable = false) 19 | private String name; 20 | 21 | @Column(nullable = false) 22 | private String username; 23 | 24 | @Column(nullable = false) 25 | private String password; 26 | 27 | private boolean isEnabled; 28 | 29 | @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) 30 | @JoinTable( 31 | name = "user_role", 32 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 33 | inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) 34 | private Set roles; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface RoleRepository extends JpaRepository {} 9 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | } 13 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/security/JwtAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.security.web.access.AccessDeniedHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAccessDeniedHandler implements AccessDeniedHandler { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void handle( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AccessDeniedException accessDeniedException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString( 31 | Map.of("error", accessDeniedException.getLocalizedMessage()))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void commence( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AuthenticationException authException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString(Map.of("error", authException.getLocalizedMessage()))); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @RequiredArgsConstructor 12 | public class UserDetailsServiceImpl implements UserDetailsService { 13 | 14 | private final UserService userService; 15 | 16 | @Override 17 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 18 | return new CustomUserDetails(userService.getByUsername(username)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/service/AuthService.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.service; 2 | 3 | import com.gucardev.springsecurityexamples.dto.LoginRequest; 4 | import com.gucardev.springsecurityexamples.dto.TokenDto; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | @Slf4j 13 | @RequiredArgsConstructor 14 | public class AuthService { 15 | 16 | private final TokenService tokenService; 17 | private final AuthenticationManager authenticationManager; 18 | 19 | public TokenDto login(LoginRequest loginRequest) { 20 | try { 21 | authenticationManager.authenticate( 22 | new UsernamePasswordAuthenticationToken( 23 | loginRequest.getUsername(), loginRequest.getPassword())); 24 | return tokenService.generateTokenPairs(loginRequest.getUsername()); 25 | } catch (Exception e) { 26 | throw new RuntimeException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /6-jwt-very-simple/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | spring: 11 | h2: 12 | console: 13 | enabled: true 14 | datasource: 15 | url: jdbc:h2:mem:db 16 | jpa: 17 | hibernate: 18 | ddl-auto: create 19 | 20 | jwt-variables: 21 | EXPIRES_ACCESS_TOKEN_MINUTE: 1 22 | ISSUER: dev 23 | KEY: asdqwe123+K3Y -------------------------------------------------------------------------------- /6-jwt-very-simple/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/7-jwt-with-refresh-token/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | @SpringBootApplication 8 | @EnableJpaAuditing 9 | public class SpringSecurityExamplesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | @PreAuthorize("hasAuthority('ADMIN')") 19 | @GetMapping("/admin") 20 | public ResponseEntity sayHelloToAdmin() { 21 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 22 | } 23 | 24 | @PreAuthorize("hasAnyAuthority('ADMIN','USER')") 25 | @GetMapping("/user") 26 | public ResponseEntity sayHelloToUser() { 27 | return ResponseEntity.ok("Hello User! This is private endpoint"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.service.RoleService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/role") 10 | public class RoleController { 11 | 12 | private final RoleService roleService; 13 | 14 | public RoleController(RoleService roleService) { 15 | this.roleService = roleService; 16 | } 17 | 18 | @GetMapping 19 | public List getRoles() { 20 | return roleService.getRoles(); 21 | } 22 | 23 | @PostMapping 24 | public RoleDto createRole(@RequestBody RoleDto userDto) { 25 | return roleService.createRole(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/users") 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | public UserController(UserService userService) { 15 | this.userService = userService; 16 | } 17 | 18 | @GetMapping 19 | public List getUsers() { 20 | return userService.getUsers(); 21 | } 22 | 23 | @PostMapping 24 | public UserDto createUser(@RequestBody UserDto userDto) { 25 | return userService.createUser(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/dto/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LoginRequest { 8 | @NotBlank private String username; 9 | @NotBlank private String password; 10 | } 11 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/dto/RefreshTokenRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class RefreshTokenRequest { 8 | @NotBlank private String refreshToken; 9 | } 10 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @Getter 11 | @Setter 12 | public class RoleDto extends BaseDto { 13 | 14 | @Null(groups = {CreateValidationGroup.class}) 15 | @NotNull(groups = {UpdateValidationGroup.class}) 16 | private Long id; 17 | 18 | private String name; 19 | } 20 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/dto/TokenDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class TokenDto { 13 | private String accessToken; 14 | private String refreshToken; 15 | private UserDto user; 16 | } 17 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import java.util.Set; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | public class UserDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | 21 | private String username; 22 | 23 | @NotNull(groups = {CreateValidationGroup.class}) 24 | @Null(groups = {UpdateValidationGroup.class}) 25 | private String password; 26 | 27 | private boolean isEnabled; 28 | 29 | private Set roles; 30 | } 31 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import org.mapstruct.BeanMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.MappingTarget; 8 | import org.mapstruct.NullValuePropertyMappingStrategy; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface RoleMapper { 12 | 13 | RoleDto toDto(Role role); 14 | 15 | Role toEntity(RoleDto role); 16 | 17 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 18 | void updatePartial(@MappingTarget Role entity, RoleDto dto); 19 | } 20 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/model/Authorities.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public class Authorities {} 4 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | @Entity 12 | @Table(name = "ROLES") 13 | @Getter 14 | @Setter 15 | public class Role extends BaseEntity implements GrantedAuthority { 16 | 17 | @Column(name = "role_name") 18 | private String name; 19 | 20 | @ManyToMany( 21 | fetch = FetchType.LAZY, 22 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 23 | mappedBy = "roles") 24 | @JsonIgnore 25 | private Set users = new HashSet<>(); 26 | 27 | @Override 28 | public String getAuthority() { 29 | return getName(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/model/Token.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.time.Instant; 5 | import lombok.Data; 6 | 7 | @Data 8 | @Entity(name = "TOKEN") 9 | public class Token { 10 | @Id 11 | @GeneratedValue(strategy = GenerationType.IDENTITY) 12 | private long id; 13 | 14 | private String username; 15 | 16 | @Column(nullable = false, unique = true, length = 2000) 17 | private String token; 18 | 19 | @Column private Instant expiryDate; 20 | 21 | private boolean valid; 22 | } 23 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Collection; 5 | import java.util.Set; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | @Entity 11 | @Table(name = "USERS") 12 | @Getter 13 | @Setter 14 | public class User extends BaseEntity { 15 | 16 | @Column(nullable = false) 17 | private String name; 18 | 19 | @Column(nullable = false) 20 | private String username; 21 | 22 | @Column(nullable = false) 23 | private String password; 24 | 25 | private boolean isEnabled; 26 | 27 | @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) 28 | @JoinTable( 29 | name = "user_role", 30 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 31 | inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) 32 | private Set roles; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface RoleRepository extends JpaRepository {} 9 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/repository/TokenRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Token; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface TokenRepository extends JpaRepository { 10 | 11 | Optional findTokenByTokenAndValidTrue(String token); 12 | } 13 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | } 13 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/security/JwtAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.security.web.access.AccessDeniedHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAccessDeniedHandler implements AccessDeniedHandler { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void handle( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AccessDeniedException accessDeniedException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString( 31 | Map.of("error", accessDeniedException.getLocalizedMessage()))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void commence( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AuthenticationException authException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString(Map.of("error", authException.getLocalizedMessage()))); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @RequiredArgsConstructor 12 | public class UserDetailsServiceImpl implements UserDetailsService { 13 | 14 | private final UserService userService; 15 | 16 | @Override 17 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 18 | return new CustomUserDetails(userService.getByUsername(username)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | spring: 11 | h2: 12 | console: 13 | enabled: true 14 | datasource: 15 | url: jdbc:h2:mem:db 16 | jpa: 17 | hibernate: 18 | ddl-auto: create 19 | 20 | jwt-variables: 21 | EXPIRES_ACCESS_TOKEN_MINUTE: 1 22 | EXPIRES_REFRESH_TOKEN_MINUTE: 1 23 | ISSUER: dev 24 | KEY: asdqwe123+K3Y -------------------------------------------------------------------------------- /7-jwt-with-refresh-token/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /8-jwt-and-otp/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /8-jwt-and-otp/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/8-jwt-and-otp/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /8-jwt-and-otp/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | @SpringBootApplication 8 | @EnableJpaAuditing 9 | public class SpringSecurityExamplesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.servlet.ModelAndView; 6 | 7 | @Controller 8 | public class HomeController { 9 | 10 | @RequestMapping("/") 11 | public ModelAndView indexHtml() { 12 | return new ModelAndView("index"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | @PreAuthorize("hasAuthority('ADMIN')") 19 | @GetMapping("/admin") 20 | public ResponseEntity sayHelloToAdmin() { 21 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 22 | } 23 | 24 | @PreAuthorize("hasAnyAuthority('ADMIN','USER')") 25 | @GetMapping("/user") 26 | public ResponseEntity sayHelloToUser() { 27 | return ResponseEntity.ok("Hello User! This is private endpoint"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.service.RoleService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/role") 10 | public class RoleController { 11 | 12 | private final RoleService roleService; 13 | 14 | public RoleController(RoleService roleService) { 15 | this.roleService = roleService; 16 | } 17 | 18 | @GetMapping 19 | public List getRoles() { 20 | return roleService.getRoles(); 21 | } 22 | 23 | @PostMapping 24 | public RoleDto createRole(@RequestBody RoleDto userDto) { 25 | return roleService.createRole(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/users") 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | public UserController(UserService userService) { 15 | this.userService = userService; 16 | } 17 | 18 | @GetMapping 19 | public List getUsers() { 20 | return userService.getUsers(); 21 | } 22 | 23 | @PostMapping 24 | public UserDto createUser(@RequestBody UserDto userDto) { 25 | return userService.createUser(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LoginRequest { 8 | @NotBlank private String username; 9 | @NotBlank private String password; 10 | } 11 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/PasswordForgetRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class PasswordForgetRequest { 9 | private String email; 10 | } 11 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/RefreshTokenRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class RefreshTokenRequest { 8 | @NotBlank private String refreshToken; 9 | } 10 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | 11 | @Getter 12 | @Setter 13 | public class RoleDto extends BaseDto { 14 | 15 | @Null(groups = {CreateValidationGroup.class}) 16 | @NotNull(groups = {UpdateValidationGroup.class}) 17 | private Long id; 18 | 19 | private String name; 20 | } 21 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/SetNewPasswordRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class SetNewPasswordRequest { 9 | private String password; 10 | private String username; 11 | private String code; 12 | } 13 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/TokenDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class TokenDto { 13 | private String accessToken; 14 | private String refreshToken; 15 | private UserDto user; 16 | } 17 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.persistence.*; 6 | import jakarta.validation.constraints.NotNull; 7 | import jakarta.validation.constraints.Null; 8 | import java.util.Set; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @Getter 13 | @Setter 14 | public class UserDto extends BaseDto { 15 | 16 | private String email; 17 | 18 | @Null(groups = {CreateValidationGroup.class}) 19 | @NotNull(groups = {UpdateValidationGroup.class}) 20 | private Long id; 21 | 22 | private String name; 23 | 24 | private String username; 25 | 26 | @NotNull(groups = {CreateValidationGroup.class}) 27 | @Null(groups = {UpdateValidationGroup.class}) 28 | private String password; 29 | 30 | private boolean isEnabled; 31 | 32 | private Set roles; 33 | } 34 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/event/UserRegisterEvent.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.event; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.springframework.context.ApplicationEvent; 7 | 8 | @Getter 9 | @Setter 10 | public class UserRegisterEvent extends ApplicationEvent { 11 | private UserDto user; 12 | 13 | public UserRegisterEvent(Object source, UserDto user) { 14 | super(source); 15 | this.user = user; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/event/listener/UserRegisterEventListener.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.event.listener; 2 | 3 | import com.gucardev.springsecurityexamples.event.UserRegisterEvent; 4 | import com.gucardev.springsecurityexamples.service.OTPService; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.context.ApplicationListener; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | @RequiredArgsConstructor 13 | @Slf4j 14 | public class UserRegisterEventListener implements ApplicationListener { 15 | 16 | private final OTPService otpService; 17 | 18 | @Value("${application-details.account-activate-url}") 19 | private String accountActivateUrl; 20 | 21 | @Override 22 | public void onApplicationEvent(UserRegisterEvent event) { 23 | log.info("user registered: {}", event.getUser().getUsername()); 24 | var otp = otpService.createOTPForAccountActivate(event.getUser().getUsername()); 25 | log.info("activate url: {}", accountActivateUrl.formatted(otp.getUsername(), otp.getCode())); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import org.mapstruct.BeanMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.MappingTarget; 8 | import org.mapstruct.NullValuePropertyMappingStrategy; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface RoleMapper { 12 | 13 | RoleDto toDto(Role role); 14 | 15 | Role toEntity(RoleDto role); 16 | 17 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 18 | void updatePartial(@MappingTarget Role entity, RoleDto dto); 19 | } 20 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/model/Authorities.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public class Authorities {} 4 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/model/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.time.LocalDateTime; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.SuperBuilder; 9 | import org.hibernate.annotations.CreationTimestamp; 10 | import org.hibernate.annotations.UpdateTimestamp; 11 | import org.springframework.data.annotation.CreatedBy; 12 | import org.springframework.data.annotation.LastModifiedBy; 13 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 14 | 15 | @MappedSuperclass 16 | @SuperBuilder 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Data 20 | @EntityListeners(AuditingEntityListener.class) 21 | public abstract class BaseEntity { 22 | 23 | @Id 24 | @GeneratedValue(strategy = GenerationType.IDENTITY) 25 | private Long id; 26 | 27 | @CreationTimestamp 28 | @Column(name = "created_at") 29 | private LocalDateTime createdDateTime; 30 | 31 | @UpdateTimestamp 32 | @Column(name = "updated_at") 33 | private LocalDateTime updatedDateTime; 34 | 35 | @CreatedBy 36 | @Column(name = "created_by") 37 | private String createdBy; 38 | 39 | @LastModifiedBy 40 | @Column(name = "updated_by") 41 | private String updatedBy; 42 | } 43 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/model/OTP.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.time.Instant; 5 | import lombok.*; 6 | 7 | @Data 8 | @Entity(name = "OTP") 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @ToString 13 | public class OTP extends BaseEntity { 14 | 15 | private String username; 16 | 17 | @Column(nullable = false, unique = true, length = 200) 18 | private String code; 19 | 20 | @Column private Instant expiryDate; 21 | 22 | private boolean expireNever; 23 | 24 | private OTPType otpType; 25 | } 26 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/model/OTPType.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public enum OTPType { 4 | ACC_ACTIVATION, 5 | LOGIN, 6 | PASSWORD_RESET 7 | } 8 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | @Entity 12 | @Table(name = "ROLES") 13 | @Getter 14 | @Setter 15 | public class Role extends BaseEntity implements GrantedAuthority { 16 | 17 | @Column(name = "role_name") 18 | private String name; 19 | 20 | @ManyToMany( 21 | fetch = FetchType.LAZY, 22 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 23 | mappedBy = "roles") 24 | @JsonIgnore 25 | private Set users = new HashSet<>(); 26 | 27 | @Override 28 | public String getAuthority() { 29 | return getName(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/model/Token.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.time.Instant; 5 | import lombok.Data; 6 | 7 | @Data 8 | @Entity(name = "TOKEN") 9 | public class Token { 10 | @Id 11 | @GeneratedValue(strategy = GenerationType.IDENTITY) 12 | private long id; 13 | 14 | private String username; 15 | 16 | @Column(nullable = false, unique = true, length = 2000) 17 | private String token; 18 | 19 | @Column private Instant expiryDate; 20 | 21 | private boolean valid; 22 | } 23 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Set; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Entity 9 | @Table(name = "USERS") 10 | @Getter 11 | @Setter 12 | public class User extends BaseEntity { 13 | 14 | @Column(nullable = false) 15 | private String name; 16 | 17 | @Column(nullable = false) 18 | private String username; 19 | 20 | @Column(nullable = false) 21 | private String email; 22 | 23 | @Column(nullable = false) 24 | private String password; 25 | 26 | private boolean isEnabled; 27 | 28 | @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) 29 | @JoinTable( 30 | name = "user_role", 31 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 32 | inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) 33 | private Set roles; 34 | } 35 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/repository/OTPRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.OTP; 4 | import com.gucardev.springsecurityexamples.model.OTPType; 5 | import java.util.Optional; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | public interface OTPRepository extends JpaRepository { 11 | 12 | Optional findByCode(String code); 13 | 14 | void deleteByCodeAndUsername(String code, String username); 15 | 16 | Optional findByCodeAndUsernameAndOtpTypeOrderByCreatedDateTimeDesc( 17 | String code, String username, OTPType otpType); 18 | 19 | Optional findByUsernameAndOtpTypeOrderByCreatedDateTimeDesc( 20 | String username, OTPType otpType); 21 | } 22 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface RoleRepository extends JpaRepository {} 9 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/repository/TokenRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Token; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface TokenRepository extends JpaRepository { 10 | 11 | Optional findTokenByTokenAndValidTrue(String token); 12 | 13 | Optional findTokenByTokenAndValidFalse(String token); 14 | } 15 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | 13 | Optional findByUsername(String username); 14 | 15 | Optional findByEmail(String email); 16 | 17 | boolean existsByUsername(String username); 18 | 19 | boolean existsByEmail(String email); 20 | } 21 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/security/JwtAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.security.web.access.AccessDeniedHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAccessDeniedHandler implements AccessDeniedHandler { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void handle( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AccessDeniedException accessDeniedException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString( 31 | Map.of("error", accessDeniedException.getLocalizedMessage()))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void commence( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AuthenticationException authException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString(Map.of("error", authException.getLocalizedMessage()))); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @RequiredArgsConstructor 12 | public class UserDetailsServiceImpl implements UserDetailsService { 13 | 14 | private final UserService userService; 15 | 16 | @Override 17 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 18 | return new CustomUserDetails(userService.getByUsername(username)); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #spring: 2 | # datasource: 3 | # password: 1234 4 | # url: jdbc:postgresql://localhost:5432/spring_security_examples 5 | # username: postgres 6 | # jpa: 7 | # hibernate: 8 | # ddl-auto: create 9 | 10 | spring: 11 | h2: 12 | console: 13 | enabled: true 14 | datasource: 15 | url: jdbc:h2:mem:db 16 | jpa: 17 | hibernate: 18 | ddl-auto: create 19 | 20 | jwt-variables: 21 | EXPIRES_ACCESS_TOKEN_MINUTE: 1 22 | EXPIRES_REFRESH_TOKEN_MINUTE: 1 23 | ISSUER: dev 24 | KEY: asdqwe123+K3Y 25 | 26 | otp-variables: 27 | EXPIRES_ACC_ACTIVATE_CODE_MINUTE: -1 28 | EXPIRES_PASSWORD_RESET_CODE_MINUTE: 1 29 | 30 | application-details: 31 | base-context: http://localhost:8080 32 | account-activate-url: ${application-details.base-context}/auth/activate-account?username=%s&code=%s 33 | password-reset-url: ${application-details.base-context}/auth/set-new-password/ui?username=%s&code=%s 34 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/resources/templates/activationError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Account Activation Error 6 | 24 | 25 | 26 |

Account Activation Error

27 |

28 | 29 | 30 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/resources/templates/activationSuccess.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Account Activation Success 6 | 24 | 25 | 26 |

Account Activation Success

27 |

Now you can close this page.

28 | 29 | 30 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Welcome 6 | 21 | 22 | 23 |

Welcome

24 | 25 | 26 | -------------------------------------------------------------------------------- /8-jwt-and-otp/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanucar/spring-security-examples/27d4d33aea1092601bc2f1bf474a2369d2740edf/9-jwt-and-oauth2-social-login/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(SpringSecurityExamplesApplication.class); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplication.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 6 | 7 | @SpringBootApplication 8 | @EnableJpaAuditing 9 | public class SpringSecurityExamplesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringSecurityExamplesApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.servlet.ModelAndView; 7 | 8 | @Controller 9 | public class HomeController { 10 | 11 | @RequestMapping("/") 12 | public ModelAndView indexHtml() { 13 | return new ModelAndView("index"); 14 | } 15 | 16 | @RequestMapping("/oauth2/redirect-success") 17 | public ModelAndView callBack(@RequestParam(name = "token", required = false) String token) { 18 | ModelAndView mav = new ModelAndView("callBack"); 19 | mav.addObject("token", token); 20 | return mav; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/controller/PrivateTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/private") 11 | public class PrivateTestController { 12 | 13 | @GetMapping 14 | public ResponseEntity sayHelloToAnyAuthenticated() { 15 | return ResponseEntity.ok("Hello Any Authenticated! This is private endpoint"); 16 | } 17 | 18 | @PreAuthorize("hasAuthority('ADMIN')") 19 | @GetMapping("/admin") 20 | public ResponseEntity sayHelloToAdmin() { 21 | return ResponseEntity.ok("Hello Admin! This is private endpoint"); 22 | } 23 | 24 | @PreAuthorize("hasAnyAuthority('ADMIN','USER')") 25 | @GetMapping("/user") 26 | public ResponseEntity sayHelloToUser() { 27 | return ResponseEntity.ok("Hello User! This is private endpoint"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/controller/PublicTestController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/public") 10 | public class PublicTestController { 11 | 12 | @GetMapping 13 | public ResponseEntity sayHello() { 14 | return ResponseEntity.ok("Hello! This is public endpoint"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.service.RoleService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/role") 10 | public class RoleController { 11 | 12 | private final RoleService roleService; 13 | 14 | public RoleController(RoleService roleService) { 15 | this.roleService = roleService; 16 | } 17 | 18 | @GetMapping 19 | public List getRoles() { 20 | return roleService.getRoles(); 21 | } 22 | 23 | @PostMapping 24 | public RoleDto createRole(@RequestBody RoleDto userDto) { 25 | return roleService.createRole(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.controller; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.service.UserService; 5 | import java.util.List; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | @RestController 9 | @RequestMapping("/users") 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | public UserController(UserService userService) { 15 | this.userService = userService; 16 | } 17 | 18 | @GetMapping 19 | public List getUsers() { 20 | return userService.getUsers(); 21 | } 22 | 23 | @PostMapping 24 | public UserDto createUser(@RequestBody UserDto userDto) { 25 | return userService.createUser(userDto); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/BaseDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.Null; 4 | import java.time.LocalDateTime; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class BaseDto { 11 | 12 | // these are must be null in requests and set in backend 13 | @Null private LocalDateTime createdDateTime; 14 | 15 | @Null private LocalDateTime updatedDateTime; 16 | 17 | @Null private String createdBy; 18 | 19 | @Null private String updatedBy; 20 | } 21 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LoginRequest { 8 | @NotBlank private String username; 9 | @NotBlank private String password; 10 | } 11 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/PasswordForgetRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class PasswordForgetRequest { 9 | private String email; 10 | } 11 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/RefreshTokenRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class RefreshTokenRequest { 8 | @NotBlank private String refreshToken; 9 | } 10 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 4 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 5 | import jakarta.validation.constraints.NotNull; 6 | import jakarta.validation.constraints.Null; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @Getter 11 | @Setter 12 | public class RoleDto extends BaseDto { 13 | 14 | @Null(groups = {CreateValidationGroup.class}) 15 | @NotNull(groups = {UpdateValidationGroup.class}) 16 | private Long id; 17 | 18 | private String name; 19 | } 20 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/SetNewPasswordRequest.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class SetNewPasswordRequest { 9 | private String password; 10 | private String username; 11 | private String code; 12 | } 13 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/TokenDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class TokenDto { 13 | private String accessToken; 14 | private String refreshToken; 15 | private UserDto user; 16 | } 17 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.dto; 2 | 3 | import com.gucardev.springsecurityexamples.model.OAuth2Provider; 4 | import com.gucardev.springsecurityexamples.validation.CreateValidationGroup; 5 | import com.gucardev.springsecurityexamples.validation.UpdateValidationGroup; 6 | import jakarta.persistence.*; 7 | import jakarta.validation.constraints.NotNull; 8 | import jakarta.validation.constraints.Null; 9 | import java.util.Set; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | 13 | @Getter 14 | @Setter 15 | public class UserDto extends BaseDto { 16 | 17 | private String email; 18 | 19 | @Null(groups = {CreateValidationGroup.class}) 20 | @NotNull(groups = {UpdateValidationGroup.class}) 21 | private Long id; 22 | 23 | private String name; 24 | 25 | private OAuth2Provider oAuth2Provider; 26 | 27 | private String username; 28 | 29 | private String password; 30 | 31 | private boolean isEnabled; 32 | 33 | private Set roles; 34 | } 35 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/event/UserRegisterEvent.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.event; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.springframework.context.ApplicationEvent; 7 | 8 | @Getter 9 | @Setter 10 | public class UserRegisterEvent extends ApplicationEvent { 11 | private UserDto user; 12 | 13 | public UserRegisterEvent(Object source, UserDto user) { 14 | super(source); 15 | this.user = user; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/event/listener/UserRegisterEventListener.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.event.listener; 2 | 3 | import com.gucardev.springsecurityexamples.event.UserRegisterEvent; 4 | import com.gucardev.springsecurityexamples.service.OTPService; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.context.ApplicationListener; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | @RequiredArgsConstructor 13 | @Slf4j 14 | public class UserRegisterEventListener implements ApplicationListener { 15 | 16 | private final OTPService otpService; 17 | 18 | @Value("${application-details.account-activate-url}") 19 | private String accountActivateUrl; 20 | 21 | @Override 22 | public void onApplicationEvent(UserRegisterEvent event) { 23 | log.info("user registered: {}", event.getUser().getUsername()); 24 | var otp = otpService.createOTPForAccountActivate(event.getUser().getUsername()); 25 | log.info("activate url: {}", accountActivateUrl.formatted(otp.getUsername(), otp.getCode())); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.RoleDto; 4 | import com.gucardev.springsecurityexamples.model.Role; 5 | import org.mapstruct.BeanMapping; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.MappingTarget; 8 | import org.mapstruct.NullValuePropertyMappingStrategy; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface RoleMapper { 12 | 13 | RoleDto toDto(Role role); 14 | 15 | Role toEntity(RoleDto role); 16 | 17 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 18 | void updatePartial(@MappingTarget Role entity, RoleDto dto); 19 | } 20 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.mapper; 2 | 3 | import com.gucardev.springsecurityexamples.dto.UserDto; 4 | import com.gucardev.springsecurityexamples.model.User; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface UserMapper { 9 | 10 | UserDto toDto(User entity); 11 | 12 | User toEntity(UserDto entity); 13 | 14 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 15 | void updatePartial(@MappingTarget User entity, UserDto dto); 16 | } 17 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/model/Authorities.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public class Authorities {} 4 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/model/OAuth2Provider.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public enum OAuth2Provider { 4 | LOCAL, GITHUB, GOOGLE 5 | } 6 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/model/OTP.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.time.Instant; 5 | import lombok.*; 6 | 7 | @Data 8 | @Entity(name = "OTP") 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @ToString 13 | public class OTP extends BaseEntity { 14 | 15 | private String username; 16 | 17 | @Column(nullable = false, unique = true, length = 200) 18 | private String code; 19 | 20 | @Column private Instant expiryDate; 21 | 22 | private boolean expireNever; 23 | 24 | private OTPType otpType; 25 | } 26 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/model/OTPType.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | public enum OTPType { 4 | ACC_ACTIVATION, 5 | LOGIN, 6 | PASSWORD_RESET 7 | } 8 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | @Entity 12 | @Table(name = "ROLES") 13 | @Getter 14 | @Setter 15 | public class Role extends BaseEntity implements GrantedAuthority { 16 | 17 | @Column(name = "role_name") 18 | private String name; 19 | 20 | @ManyToMany( 21 | fetch = FetchType.LAZY, 22 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 23 | mappedBy = "roles") 24 | @JsonIgnore 25 | private Set users = new HashSet<>(); 26 | 27 | @Override 28 | public String getAuthority() { 29 | return getName(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/model/Token.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.time.Instant; 5 | import lombok.Data; 6 | 7 | @Data 8 | @Entity(name = "TOKEN") 9 | public class Token { 10 | @Id 11 | @GeneratedValue(strategy = GenerationType.IDENTITY) 12 | private long id; 13 | 14 | private String username; 15 | 16 | @Column(nullable = false, unique = true, length = 2000) 17 | private String token; 18 | 19 | @Column private Instant expiryDate; 20 | 21 | private boolean valid; 22 | } 23 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/model/User.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.model; 2 | 3 | import jakarta.persistence.*; 4 | import java.util.Set; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Entity 9 | @Table(name = "USERS") 10 | @Getter 11 | @Setter 12 | public class User extends BaseEntity { 13 | 14 | @Column(nullable = false) 15 | private String name; 16 | 17 | @Column(nullable = false) 18 | private String username; 19 | 20 | @Column(nullable = false) 21 | private String email; 22 | 23 | // @Column(nullable = false) 24 | private String password; 25 | 26 | @Enumerated(EnumType.STRING) 27 | private OAuth2Provider oAuth2Provider; 28 | 29 | private boolean isEnabled; 30 | 31 | @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) 32 | @JoinTable( 33 | name = "user_role", 34 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 35 | inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) 36 | private Set roles; 37 | } 38 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/repository/OTPRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.OTP; 4 | import com.gucardev.springsecurityexamples.model.OTPType; 5 | import java.util.Optional; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | public interface OTPRepository extends JpaRepository { 11 | 12 | Optional findByCode(String code); 13 | 14 | void deleteByCodeAndUsername(String code, String username); 15 | 16 | Optional findByCodeAndUsernameAndOtpTypeOrderByCreatedDateTimeDesc( 17 | String code, String username, OTPType otpType); 18 | 19 | Optional findByUsernameAndOtpTypeOrderByCreatedDateTimeDesc( 20 | String username, OTPType otpType); 21 | } 22 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Role; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface RoleRepository extends JpaRepository {} 9 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/repository/TokenRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.Token; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface TokenRepository extends JpaRepository { 10 | 11 | Optional findTokenByTokenAndValidTrue(String token); 12 | 13 | Optional findTokenByTokenAndValidFalse(String token); 14 | } 15 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.repository; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | 11 | Optional findByUsernameAndIsEnabledTrue(String username); 12 | 13 | Optional findByUsername(String username); 14 | 15 | Optional findByEmail(String email); 16 | 17 | boolean existsByUsername(String username); 18 | 19 | boolean existsByEmail(String email); 20 | } 21 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/security/CustomOauthUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.model.OAuth2Provider; 4 | import java.util.Collection; 5 | import java.util.Map; 6 | import lombok.Data; 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.oauth2.core.user.OAuth2User; 9 | 10 | @Data 11 | public class CustomOauthUserDetails implements OAuth2User { 12 | private Long id; 13 | private String username; 14 | private String name; 15 | private String email; 16 | private String avatarUrl; 17 | private OAuth2Provider provider; 18 | private Collection authorities; 19 | private Map attributes; 20 | } 21 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/security/CustomUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.model.User; 4 | import java.util.Collection; 5 | import lombok.Data; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | 9 | @Data 10 | public class CustomUserDetails implements UserDetails { 11 | 12 | private User user; 13 | 14 | public CustomUserDetails(User user) { 15 | this.user = user; 16 | } 17 | 18 | @Override 19 | public String getPassword() { 20 | return this.user.getPassword(); 21 | } 22 | 23 | @Override 24 | public String getUsername() { 25 | return this.user.getUsername(); 26 | } 27 | 28 | @Override 29 | public boolean isAccountNonExpired() { 30 | return true; 31 | } 32 | 33 | @Override 34 | public boolean isAccountNonLocked() { 35 | return true; 36 | } 37 | 38 | @Override 39 | public boolean isCredentialsNonExpired() { 40 | return true; 41 | } 42 | 43 | @Override 44 | public boolean isEnabled() { 45 | return this.user.isEnabled(); 46 | } 47 | 48 | @Override 49 | public Collection getAuthorities() { 50 | return this.user.getRoles(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/security/JwtAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.security.web.access.AccessDeniedHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAccessDeniedHandler implements AccessDeniedHandler { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void handle( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AccessDeniedException accessDeniedException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString( 31 | Map.of("error", accessDeniedException.getLocalizedMessage()))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.util.Map; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | @RequiredArgsConstructor 15 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { 16 | 17 | private final ObjectMapper objectMapper; 18 | 19 | @Override 20 | public void commence( 21 | HttpServletRequest request, 22 | HttpServletResponse response, 23 | AuthenticationException authException) 24 | throws IOException { 25 | response.setContentType("application/json"); 26 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 27 | response 28 | .getWriter() 29 | .write( 30 | objectMapper.writeValueAsString(Map.of("error", authException.getLocalizedMessage()))); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class PasswordEncoderConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security; 2 | 3 | import com.gucardev.springsecurityexamples.service.UserService; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @RequiredArgsConstructor 12 | public class UserDetailsServiceImpl implements UserDetailsService { 13 | 14 | private final UserService userService; 15 | 16 | @Override 17 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 18 | return new CustomUserDetails(userService.getByUsername(username)); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/security/oauth/OAuth2UserInfoExtractor.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.security.oauth; 2 | 3 | import com.gucardev.springsecurityexamples.security.CustomOauthUserDetails; 4 | import com.gucardev.springsecurityexamples.security.CustomUserDetails; 5 | import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; 6 | import org.springframework.security.oauth2.core.user.OAuth2User; 7 | 8 | public interface OAuth2UserInfoExtractor { 9 | 10 | CustomOauthUserDetails extractUserInfo(OAuth2User oAuth2User); 11 | 12 | boolean accepts(OAuth2UserRequest userRequest); 13 | } 14 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/validation/CreateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface CreateValidationGroup {} 4 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/java/com/gucardev/springsecurityexamples/validation/UpdateValidationGroup.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples.validation; 2 | 3 | public interface UpdateValidationGroup {} 4 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/resources/templates/activationError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Account Activation Error 6 | 24 | 25 | 26 |

Account Activation Error

27 |

28 | 29 | 30 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/resources/templates/activationSuccess.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Account Activation Success 6 | 24 | 25 | 26 |

Account Activation Success

27 |

Now you can close this page.

28 | 29 | 30 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/resources/templates/callBack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Callback 6 | 34 | 35 | 36 | 37 |

OAUTH2 Login Success

38 |
39 |

your token is:

40 |

41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Welcome 6 | 21 | 22 | 23 |

Welcome

24 | 25 | 26 | -------------------------------------------------------------------------------- /9-jwt-and-oauth2-social-login/src/test/java/com/gucardev/springsecurityexamples/SpringSecurityExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.gucardev.springsecurityexamples; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringSecurityExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | --------------------------------------------------------------------------------