├── LICENSE ├── README.md ├── _config.yml ├── authentication ├── .gitignore ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── authentication │ │ │ ├── Application.java │ │ │ ├── api │ │ │ └── AuthenticationAPI.java │ │ │ ├── config │ │ │ ├── AuthorizationServerConfig.java │ │ │ ├── PersistentContext.java │ │ │ ├── ResourceServerConfiguration.java │ │ │ ├── SwaggerConfig.java │ │ │ ├── WebSecurityConfig.java │ │ │ └── package-info.java │ │ │ ├── model │ │ │ ├── User.java │ │ │ └── UserTokenSession.java │ │ │ ├── repository │ │ │ ├── UserRepository.java │ │ │ └── UserTokenSessionRepository.java │ │ │ └── service │ │ │ ├── UserDetailsServiceImpl.java │ │ │ ├── UserTokenSessionService.java │ │ │ └── UserTokenSessionServiceImpl.java │ └── resources │ │ ├── application.properties │ │ ├── data.sql │ │ ├── images │ │ ├── Swagger-UI-Home.png │ │ ├── Swagger-ui-auth.png │ │ ├── swagger-ui-login-token.png │ │ └── swagger-ui-login.png │ │ └── schema.sql │ └── test │ ├── java │ └── com │ │ └── authentication │ │ ├── api │ │ ├── AuthenticationAPITest.java │ │ └── OAuthHelper.java │ │ └── service │ │ ├── UserDetailsServiceTest.java │ │ └── UserTokenSessionServiceTest.java │ └── resources │ └── application.properties └── oauthswager /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Rohit Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-oauth2-jwt-swagger-ui 2 | Spring Boot , OAuth 2 , JWT (Json Web Token) and Swagger UI 3 | 4 | # Spring Boot + OAuth 2.0 + JWT + Swagger-UI 2? 5 | 6 | ## How to start ? 7 | 8 | ``` 9 | $ mvn spring-boot:run 10 | ``` 11 | 12 | ## Swagger-UI 13 | * After starting the application Click on [Swagger-home](http://localhost:8080/api/swagger-ui.html) 14 | 15 | ![Swagger-Home](/authentication/src/main/resources/images/Swagger-UI-Home.png "Swagger UI Home") 16 | 17 | 18 | ## User Data 19 | 20 | ``` 21 | user-name | password 22 | user1@example.com | password 23 | user2@example.com | password 24 | user3@example.com | password 25 | ``` 26 | 27 | 28 | ## Authorize 29 | * Use above given user details to login and generate the authorization token. 30 | ![Swagger-Home](/authentication/src/main/resources/images/Swagger-ui-auth.png "Swagger UI Home") 31 | 32 | ![Swagger-Home](/authentication/src/main/resources/images/swagger-ui-login.png "Swagger UI Home") 33 | 34 | * Login using the generated token 35 | ![Swagger-Home](/authentication/src/main/resources/images/swagger-ui-login-token.png "Swagger UI Home") 36 | 37 | 38 | 39 | ## Change OAuth configuration 40 | * Edit the configuration in the file [application.properties](/authentication/src/main/resources/application.properties) 41 | 42 | ``` 43 | server.port=8080 44 | server.contextPath=/api 45 | 46 | logging.level.com.alfred=DEBUG 47 | 48 | # Data source properties 49 | spring.jpa.hibernate.ddl-auto=validate 50 | spring.jpa.show-sql=true 51 | 52 | # openssl genrsa -out jwt.pem 2048 53 | # openssl rsa -in jwt.pem 54 | config.oauth2.privateKey=MIICXQIBAAKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQABAoGAImnYGU3ApPOVtBf/TOqLfne+2SZX96eVU06myDY3zA4rO3DfbR7CzCLE6qPnyDAIiW0UQBs0oBDdWOnOqz5YaePZu/yrLyj6KM6Q2e9ywRDtDh3ywrSfGpjdSvvoaeL1WesBWsgWv1vFKKvES7ILFLUxKwyCRC2Lgh7aI9GGZfECQQD84m98Yrehhin3fZuRaBNIu348Ci7ZFZmrvyxAIxrV4jBjpACW0RM2BvF5oYM2gOJqIfBOVjmPwUrobYEFcHRvAkEAz8jsfmxsZVwh3Y/Y47BzhKIC5FLaads541jNjVWfrPirljyCy1n4sg3WQH2IEyap3WTP84+csCtsfNfyK7fQdwJBAJNRyobY74cupJYkW5OK4OkXKQQLHp2iosJV/Y5jpQeC3JO/gARcSmfIBbbI66q9zKjtmpPYUXI4tc3PtUEY8QsCQQCcxySyC0sKe6bNzyC+Q8AVvkxiTKWiI5idEr8duhJd589H72Zc2wkMB+a2CEGo+Y5Hjy5cvuph/pG/7Qw7sljnAkAy/feClt1mUEiAcWrHRwcQ71AoA0+21yC9VkqPNrn3w7OEg8gBqPjRlXBNb00QieNeGGSkXOoU6gFschR22Dzy 55 | 56 | # openssl rsa -in jwt.pem -pubout 57 | config.oauth2.publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQAB 58 | 59 | 60 | #oauth configurations 61 | config.oauth2.tokenTimeout=3600 62 | config.oauth2.resource.id=oauth2-resource 63 | config.oauth2.clientID=client 64 | config.oauth2.clientSecret=secret 65 | security.oauth2.client.grantType=client_credentials 66 | config.oauth2.accessTokenUri=http://localhost:8080/api/oauth/token 67 | config.oauth2.userAuthorizationUri=http://localhost:8080/api/oauth/authorize 68 | config.oauth2.resourceURI= http://localhost:8080/api/oauth/authorize 69 | ``` 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-merlot -------------------------------------------------------------------------------- /authentication/.gitignore: -------------------------------------------------------------------------------- 1 | #target 2 | */target/* 3 | target/* 4 | #intellij-files 5 | *.idea/* 6 | *.iml 7 | *.DS_Store 8 | *-pom.xml 9 | RemoteSystemsTempFiles/* 10 | .svn/* 11 | .settings/ 12 | .project 13 | .metadata/ 14 | .idea/ 15 | .classpath 16 | ../.DS_Store 17 | .idea/libraries/Maven* -------------------------------------------------------------------------------- /authentication/README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot + OAuth 2.0 + JWT + Swagger-UI 2? 2 | 3 | ## How to start ? 4 | 5 | ``` 6 | $ mvn spring-boot:run 7 | ``` 8 | 9 | ## Swagger-UI 10 | * After starting the application Click on [Swagger-home](http://localhost:8080/api/swagger-ui.html) 11 | 12 | ![Swagger-Home](/authentication/src/main/resources/images/Swagger-UI-Home.png "Swagger UI Home") 13 | 14 | 15 | ## User Data 16 | 17 | ``` 18 | user-name | password 19 | user1@example.com | password 20 | user2@example.com | password 21 | user3@example.com | password 22 | ``` 23 | 24 | 25 | ## Authorize 26 | * Use above given user details to login and generate the authorization token. 27 | ![Swagger-Home](/authentication/src/main/resources/images/Swagger-ui-auth.png "Swagger UI Home") 28 | 29 | ![Swagger-Home](/authentication/src/main/resources/images/swagger-ui-login.png "Swagger UI Home") 30 | 31 | * Login using the generated token 32 | ![Swagger-Home](/authentication/src/main/resources/images/swagger-ui-login-token.png "Swagger UI Home") 33 | 34 | 35 | 36 | ## Change OAuth configuration 37 | * Edit the configuration in the file [application.properties](/authentication/src/main/resources/application.properties) 38 | 39 | ``` 40 | server.port=8080 41 | server.contextPath=/api 42 | 43 | logging.level.com.alfred=DEBUG 44 | 45 | # Data source properties 46 | spring.jpa.hibernate.ddl-auto=validate 47 | spring.jpa.show-sql=true 48 | 49 | # openssl genrsa -out jwt.pem 2048 50 | # openssl rsa -in jwt.pem 51 | config.oauth2.privateKey=MIICXQIBAAKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQABAoGAImnYGU3ApPOVtBf/TOqLfne+2SZX96eVU06myDY3zA4rO3DfbR7CzCLE6qPnyDAIiW0UQBs0oBDdWOnOqz5YaePZu/yrLyj6KM6Q2e9ywRDtDh3ywrSfGpjdSvvoaeL1WesBWsgWv1vFKKvES7ILFLUxKwyCRC2Lgh7aI9GGZfECQQD84m98Yrehhin3fZuRaBNIu348Ci7ZFZmrvyxAIxrV4jBjpACW0RM2BvF5oYM2gOJqIfBOVjmPwUrobYEFcHRvAkEAz8jsfmxsZVwh3Y/Y47BzhKIC5FLaads541jNjVWfrPirljyCy1n4sg3WQH2IEyap3WTP84+csCtsfNfyK7fQdwJBAJNRyobY74cupJYkW5OK4OkXKQQLHp2iosJV/Y5jpQeC3JO/gARcSmfIBbbI66q9zKjtmpPYUXI4tc3PtUEY8QsCQQCcxySyC0sKe6bNzyC+Q8AVvkxiTKWiI5idEr8duhJd589H72Zc2wkMB+a2CEGo+Y5Hjy5cvuph/pG/7Qw7sljnAkAy/feClt1mUEiAcWrHRwcQ71AoA0+21yC9VkqPNrn3w7OEg8gBqPjRlXBNb00QieNeGGSkXOoU6gFschR22Dzy 52 | 53 | # openssl rsa -in jwt.pem -pubout 54 | config.oauth2.publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQAB 55 | 56 | 57 | #oauth configurations 58 | config.oauth2.tokenTimeout=3600 59 | config.oauth2.resource.id=oauth2-resource 60 | config.oauth2.clientID=client 61 | config.oauth2.clientSecret=secret 62 | security.oauth2.client.grantType=client_credentials 63 | config.oauth2.accessTokenUri=http://localhost:8080/api/oauth/token 64 | config.oauth2.userAuthorizationUri=http://localhost:8080/api/oauth/authorize 65 | config.oauth2.resourceURI= http://localhost:8080/api/oauth/authorize 66 | ``` 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /authentication/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | authentication 7 | authentication-service 8 | 0.0.1-SNAPSHOT 9 | Authentication Service 10 | http://maven.apache.org 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 1.5.7.RELEASE 16 | 17 | 18 | 19 | UTF-8 20 | 1.8 21 | 1.8 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-security 34 | 35 | 36 | org.springframework.security.oauth 37 | spring-security-oauth2 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-data-jpa 42 | 43 | 44 | 45 | 46 | com.fasterxml.jackson.core 47 | jackson-databind 48 | 2.13.4.2 49 | 50 | 51 | com.fasterxml.jackson.core 52 | jackson-core 53 | 54 | 55 | com.fasterxml.jackson.core 56 | jackson-annotations 57 | 58 | 59 | 60 | 61 | com.fasterxml.jackson.core 62 | jackson-core 63 | 2.7.4 64 | 65 | 66 | com.fasterxml.jackson.core 67 | jackson-annotations 68 | 2.7.4 69 | 70 | 71 | 72 | 73 | org.springframework.security 74 | spring-security-jwt 75 | 1.0.8.RELEASE 76 | 77 | 78 | 79 | org.hibernate 80 | hibernate-core 81 | 5.4.24.Final 82 | 83 | 84 | org.hibernate 85 | hibernate-entitymanager 86 | 5.2.2.Final 87 | 88 | 89 | 90 | javassist 91 | javassist 92 | 3.3 93 | 94 | 95 | 96 | 97 | com.h2database 98 | h2 99 | runtime 100 | 101 | 102 | 103 | 104 | io.springfox 105 | springfox-swagger2 106 | 2.8.0 107 | 108 | 109 | io.springfox 110 | springfox-swagger-ui 111 | 2.8.0 112 | 113 | 114 | io.springfox 115 | springfox-bean-validators 116 | 2.8.0 117 | 118 | 119 | guava 120 | com.google.guava 121 | jar 122 | 18.0 123 | 124 | 125 | 126 | 127 | org.springframework.boot 128 | spring-boot-starter-test 129 | test 130 | 131 | 132 | org.mockito 133 | mockito-all 134 | 1.9.5 135 | test 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | org.springframework.boot 145 | spring-boot-maven-plugin 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/Application.java: -------------------------------------------------------------------------------- 1 | package com.authentication; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @author Rohit.Kumar 9 | */ 10 | @SpringBootApplication 11 | public class Application { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(Application.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/api/AuthenticationAPI.java: -------------------------------------------------------------------------------- 1 | package com.authentication.api; 2 | 3 | import com.authentication.model.UserTokenSession; 4 | import com.authentication.service.UserTokenSessionService; 5 | import com.authentication.service.UserTokenSessionServiceImpl; 6 | import io.swagger.annotations.*; 7 | import org.apache.log4j.Logger; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.beans.factory.annotation.Qualifier; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.http.HttpHeaders; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.http.MediaType; 14 | import org.springframework.http.ResponseEntity; 15 | import org.springframework.security.core.userdetails.UserDetailsService; 16 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 17 | import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; 18 | import org.springframework.web.bind.annotation.RequestHeader; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | import org.springframework.web.bind.annotation.RequestMethod; 21 | import org.springframework.web.bind.annotation.RestController; 22 | 23 | import javax.servlet.http.HttpServletRequest; 24 | import java.security.Principal; 25 | import java.util.Objects; 26 | 27 | /** 28 | * @author Rohit.Kumar 29 | * @version 0.01 30 | */ 31 | @RestController 32 | @RequestMapping("/oauth") 33 | @Api(value="Authentication API", description="Authenticate user using authorization token.") 34 | public class AuthenticationAPI { 35 | 36 | private static final Logger LOGGER = Logger.getLogger(AuthenticationAPI.class); 37 | 38 | @Autowired 39 | @Qualifier("userDetailsService") 40 | private UserDetailsService userDetailsService; 41 | 42 | @Value("${config.oauth2.tokenTimeout}") 43 | private long tokenExpiryTime; 44 | 45 | @Autowired 46 | private UserTokenSessionServiceImpl userTokenSessionService; 47 | 48 | 49 | @ApiOperation(value = "Authenticated User Login", response = UserTokenSession.class) 50 | @RequestMapping(value = "/login", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) 51 | @ApiResponses(value = { 52 | @ApiResponse(code = 200, message = "Success", response = UserTokenSession.class), 53 | @ApiResponse(code = 401, message = "Unauthorized"), 54 | @ApiResponse(code = 403, message = "Forbidden"), 55 | @ApiResponse(code = 404, message = "Not Found"), 56 | @ApiResponse(code = 500, message = "Failure")}) 57 | public ResponseEntity login(@RequestHeader HttpHeaders httpHeaders, Principal principal, HttpServletRequest httpServletRequest) { 58 | 59 | String username = principal.getName(); 60 | UserTokenSession userTokenSession = buildUserTokenSession(principal, httpHeaders); 61 | userTokenSession = userTokenSessionService.saveUserTokenSessionMapping(userTokenSession); 62 | 63 | LOGGER.info("User "+username+" successfully logged in. User, Token and Session mapping stored."+userTokenSession); 64 | 65 | HttpHeaders responseHeaders = new HttpHeaders(); 66 | responseHeaders.add("Message", "Success"); 67 | responseHeaders.add("Set-Cookie", userTokenSession.getSessionId()); 68 | 69 | return new ResponseEntity(userTokenSession, responseHeaders, HttpStatus.OK); 70 | } 71 | 72 | @ApiOperation(value = "Validate the given token", response = UserTokenSession.class) 73 | @RequestMapping(value = "/validateToken", method = RequestMethod.POST, 74 | produces = MediaType.APPLICATION_JSON_VALUE) 75 | @ApiResponses(value = { 76 | @ApiResponse(code = 200, message = "Success", response = UserTokenSession.class), 77 | @ApiResponse(code = 401, message = "Unauthorized"), 78 | @ApiResponse(code = 403, message = "Forbidden"), 79 | @ApiResponse(code = 404, message = "Not Found"), 80 | @ApiResponse(code = 500, message = "Failure")}) 81 | public ResponseEntity validateToken(@RequestHeader HttpHeaders httpHeaders, Principal principal, HttpServletRequest httpServletRequest) { 82 | 83 | 84 | String username = principal.getName(); 85 | UserTokenSession userTokenSession = buildUserTokenSession(principal, httpHeaders); 86 | 87 | ResponseEntity responseEntity; 88 | HttpHeaders responseHeaders = new HttpHeaders(); 89 | responseHeaders.add("Set-Cookie", userTokenSession.getSessionId()); 90 | 91 | UserTokenSessionService.ValidMappingResponse validMappingResponse = userTokenSessionService.isValidUserTokenSessionMapping(userTokenSession); 92 | if (validMappingResponse.isValid()) { 93 | 94 | LOGGER.info("User " + username + " has valid token."+validMappingResponse.getUserTokenSession()); 95 | responseHeaders.add("Message", "Valid Token"); 96 | responseEntity = new ResponseEntity(validMappingResponse.getUserTokenSession(), responseHeaders, HttpStatus.OK); 97 | 98 | } else { 99 | 100 | LOGGER.info("User " + username + " has invalid token."); 101 | responseHeaders.add("Message", "Invalid Token"); 102 | responseEntity = new ResponseEntity(userTokenSession, responseHeaders, HttpStatus.UNAUTHORIZED); 103 | } 104 | 105 | return responseEntity; 106 | } 107 | 108 | /** 109 | * Build Token session using {@link Principal} and {@link HttpHeaders} 110 | * @param principal 111 | * @param httpHeaders 112 | * @return TokenSession 113 | */ 114 | private UserTokenSession buildUserTokenSession(Principal principal, HttpHeaders httpHeaders) { 115 | 116 | OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) ((OAuth2Authentication) principal).getDetails(); 117 | String tokenValue = oAuth2AuthenticationDetails.getTokenValue(); 118 | String username = principal.getName(); 119 | String [] sessionId = new String[1]; 120 | 121 | if (Objects.nonNull(httpHeaders.get("cookie"))) { 122 | sessionId = httpHeaders.get("cookie").get(0).split(";"); 123 | }else { 124 | LOGGER.info("User " + username + " cookie not found. JSessionId not set."); 125 | 126 | /** 127 | * Swagger2 does not support cookie for that putting default sessssion id. 128 | */ 129 | sessionId[0] = "JSEESION-ID"; 130 | } 131 | 132 | UserTokenSession userTokenSession = new UserTokenSession(username, tokenValue, sessionId[0], tokenExpiryTime); 133 | return userTokenSession; 134 | } 135 | 136 | 137 | } 138 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/config/AuthorizationServerConfig.java: -------------------------------------------------------------------------------- 1 | package com.authentication.config; 2 | 3 | import org.apache.log4j.Logger; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Qualifier; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Primary; 10 | import org.springframework.http.HttpMethod; 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 | import org.springframework.security.crypto.password.PasswordEncoder; 15 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 16 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 17 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 18 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 19 | import org.springframework.security.oauth2.provider.ClientDetailsService; 20 | import org.springframework.security.oauth2.provider.token.DefaultTokenServices; 21 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 22 | import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; 23 | 24 | /** 25 | * @author Rohit.Kumar 26 | */ 27 | @Configuration 28 | @EnableAuthorizationServer 29 | public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { 30 | 31 | private static final Logger LOGGER = Logger.getLogger(AuthorizationServerConfig.class); 32 | 33 | @Autowired 34 | @Qualifier("userDetailsService") 35 | private UserDetailsService userDetailsService; 36 | 37 | @Autowired 38 | private AuthenticationManager authenticationManager; 39 | 40 | @Value("${config.oauth2.tokenTimeout}") 41 | private int expiration; 42 | 43 | @Value("${config.oauth2.privateKey}") 44 | private String privateKey; 45 | 46 | @Value("${config.oauth2.publicKey}") 47 | private String publicKey; 48 | 49 | @Autowired 50 | private ClientDetailsService clientDetailsService; 51 | 52 | @Bean 53 | public PasswordEncoder passwordEncoder() { 54 | return new BCryptPasswordEncoder(); 55 | } 56 | 57 | 58 | @Override 59 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 60 | clients 61 | .inMemory() 62 | .withClient("client") 63 | .authorizedGrantTypes("client_credentials", "password", "refresh_token", "authorization_code") 64 | .scopes("read", "write") 65 | .resourceIds("oauth2-resource") 66 | .accessTokenValiditySeconds(expiration) 67 | .refreshTokenValiditySeconds(expiration) 68 | .secret("secret"); 69 | 70 | } 71 | 72 | @Bean 73 | public JwtAccessTokenConverter accessTokenConverter() { 74 | 75 | LOGGER.info("Initializing JWT with public key: " + publicKey); 76 | 77 | JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 78 | converter.setSigningKey(privateKey); 79 | 80 | return converter; 81 | } 82 | 83 | @Bean 84 | public JwtTokenStore tokenStore() { 85 | return new JwtTokenStore(accessTokenConverter()); 86 | } 87 | 88 | @Bean 89 | @Primary 90 | public DefaultTokenServices tokenServices() { 91 | DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); 92 | defaultTokenServices.setTokenStore(tokenStore()); 93 | defaultTokenServices.setClientDetailsService(clientDetailsService); 94 | defaultTokenServices.setSupportRefreshToken(true); 95 | defaultTokenServices.setTokenEnhancer(accessTokenConverter()); 96 | return defaultTokenServices; 97 | } 98 | 99 | /** 100 | * Defines the authorization and token endpoints and the token services 101 | * @param endpoints 102 | * @throws Exception 103 | */ 104 | @Override 105 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 106 | 107 | endpoints 108 | .authenticationManager(authenticationManager) 109 | .userDetailsService(userDetailsService) 110 | .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST) 111 | .tokenStore(tokenStore()) 112 | .tokenServices(tokenServices()) 113 | .accessTokenConverter(accessTokenConverter()); 114 | } 115 | 116 | 117 | 118 | } 119 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/config/PersistentContext.java: -------------------------------------------------------------------------------- 1 | package com.authentication.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.ComponentScan; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 7 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; 8 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; 9 | import org.springframework.orm.jpa.JpaTransactionManager; 10 | import org.springframework.orm.jpa.JpaVendorAdapter; 11 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 12 | import org.springframework.orm.jpa.vendor.Database; 13 | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; 14 | 15 | import javax.persistence.EntityManagerFactory; 16 | import javax.sql.DataSource; 17 | 18 | /** 19 | * @author Rohit.Kumar 20 | */ 21 | @Configuration 22 | @ComponentScan("com.authentication") 23 | @EnableJpaRepositories("com.authentication.repository") 24 | public class PersistentContext { 25 | 26 | @Bean 27 | public DataSource dataSource() { 28 | return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build(); 29 | } 30 | 31 | @Bean 32 | public JpaVendorAdapter jpaVendorAdapter() { 33 | HibernateJpaVendorAdapter bean = new HibernateJpaVendorAdapter(); 34 | bean.setDatabase(Database.H2); 35 | bean.setGenerateDdl(true); 36 | return bean; 37 | } 38 | 39 | @Bean 40 | public LocalContainerEntityManagerFactoryBean entityManagerFactory( 41 | DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) { 42 | 43 | LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean(); 44 | bean.setDataSource(dataSource); 45 | bean.setJpaVendorAdapter(jpaVendorAdapter); 46 | bean.setPackagesToScan("com.authentication"); 47 | return bean; 48 | } 49 | 50 | @Bean 51 | public JpaTransactionManager transactionManager(EntityManagerFactory emf) { 52 | return new JpaTransactionManager(emf); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/config/ResourceServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.authentication.config; 2 | 3 | import org.apache.log4j.Logger; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.annotation.Primary; 8 | import org.springframework.http.HttpMethod; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 11 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 12 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; 13 | import org.springframework.security.oauth2.provider.token.DefaultTokenServices; 14 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 15 | import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; 16 | 17 | /** 18 | * @author Rohit.Kumar 19 | */ 20 | @Configuration 21 | @EnableResourceServer 22 | public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 23 | 24 | private static final Logger LOGGER = Logger.getLogger(ResourceServerConfiguration.class); 25 | 26 | 27 | @Value("${config.oauth2.publicKey}") 28 | private String publicKey; 29 | 30 | @Value("${config.oauth2.privateKey}") 31 | private String privateKey; 32 | 33 | @Value("${config.oauth2.resource.id}") 34 | private String resourceId; 35 | 36 | 37 | @Override 38 | public void configure(HttpSecurity http) throws Exception { 39 | http 40 | .csrf().disable() 41 | .anonymous().disable() 42 | .authorizeRequests() 43 | .antMatchers(HttpMethod.OPTIONS).permitAll() 44 | .antMatchers("/oauth/**").authenticated(); 45 | 46 | } 47 | 48 | 49 | @Override 50 | public void configure(ResourceServerSecurityConfigurer resources) { 51 | resources 52 | .resourceId(resourceId) 53 | .tokenServices(tokenServices()) 54 | .tokenStore(tokenStore()); 55 | } 56 | 57 | @Bean 58 | @Primary 59 | public DefaultTokenServices tokenServices() { 60 | DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); 61 | defaultTokenServices.setTokenStore(tokenStore()); 62 | defaultTokenServices.setSupportRefreshToken(true); 63 | defaultTokenServices.setTokenEnhancer(accessTokenConverter()); 64 | return defaultTokenServices; 65 | } 66 | 67 | @Bean 68 | public JwtAccessTokenConverter accessTokenConverter() { 69 | 70 | LOGGER.info("Initializing JWT with public key: " + publicKey); 71 | 72 | JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 73 | converter.setSigningKey(privateKey); 74 | 75 | return converter; 76 | } 77 | 78 | @Bean 79 | public JwtTokenStore tokenStore() { 80 | return new JwtTokenStore(accessTokenConverter()); 81 | } 82 | 83 | 84 | } -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.authentication.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.http.HttpHeaders; 8 | import springfox.documentation.builders.ApiInfoBuilder; 9 | import springfox.documentation.builders.PathSelectors; 10 | import springfox.documentation.builders.RequestHandlerSelectors; 11 | import springfox.documentation.service.*; 12 | import springfox.documentation.spi.DocumentationType; 13 | import springfox.documentation.spi.service.contexts.SecurityContext; 14 | import springfox.documentation.spring.web.plugins.Docket; 15 | import springfox.documentation.swagger.web.ApiKeyVehicle; 16 | import springfox.documentation.swagger.web.SecurityConfiguration; 17 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 18 | 19 | import java.util.Arrays; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; 24 | 25 | /** 26 | * TODO Swagger UI to be completed, as of now there are some issues in authentication. 27 | * @author Rohit.Kumar 28 | */ 29 | @Configuration 30 | @EnableSwagger2 31 | @ComponentScan(basePackages = "com.authentication.api") 32 | public class SwaggerConfig { 33 | 34 | 35 | @Value("${config.oauth2.accessTokenUri}") 36 | private String accessTokenUri; 37 | 38 | 39 | public static final String securitySchemaOAuth2 = "oauth2schema"; 40 | public static final String authorizationScopeGlobal = "global"; 41 | public static final String authorizationScopeGlobalDesc ="accessEverything"; 42 | /** 43 | * 44 | * @return Docket 45 | */ 46 | @Bean 47 | public Docket productApi() { 48 | 49 | 50 | return new Docket(DocumentationType.SWAGGER_2) 51 | .select() 52 | .apis(RequestHandlerSelectors.any()) 53 | .paths(PathSelectors.any()) 54 | .build() 55 | .securityContexts(Collections.singletonList(securityContext())) 56 | .securitySchemes(Arrays.asList(securitySchema(), apiKey(), apiCookieKey())) 57 | .apiInfo(apiInfo()); 58 | 59 | 60 | } 61 | 62 | @Bean 63 | public SecurityScheme apiKey() { 64 | return new ApiKey(HttpHeaders.AUTHORIZATION, "apiKey", "header"); 65 | } 66 | 67 | @Bean 68 | public SecurityScheme apiCookieKey() { 69 | return new ApiKey(HttpHeaders.COOKIE, "apiKey", "cookie"); 70 | } 71 | 72 | private OAuth securitySchema() { 73 | 74 | List authorizationScopeList = newArrayList(); 75 | authorizationScopeList.add(new AuthorizationScope("read", "read all")); 76 | authorizationScopeList.add(new AuthorizationScope("write", "access all")); 77 | 78 | List grantTypes = newArrayList(); 79 | GrantType passwordCredentialsGrant = new ResourceOwnerPasswordCredentialsGrant(accessTokenUri); 80 | grantTypes.add(passwordCredentialsGrant); 81 | 82 | return new OAuth("oauth2", authorizationScopeList, grantTypes); 83 | } 84 | 85 | private SecurityContext securityContext() { 86 | return SecurityContext.builder().securityReferences(defaultAuth()) 87 | .build(); 88 | } 89 | 90 | 91 | 92 | private List defaultAuth() { 93 | 94 | final AuthorizationScope[] authorizationScopes = new AuthorizationScope[3]; 95 | authorizationScopes[0] = new AuthorizationScope("read", "read all"); 96 | authorizationScopes[1] = new AuthorizationScope("trust", "trust all"); 97 | authorizationScopes[2] = new AuthorizationScope("write", "write all"); 98 | 99 | return Collections.singletonList(new SecurityReference("oauth2", authorizationScopes)); 100 | } 101 | 102 | @Bean 103 | public SecurityConfiguration security() { 104 | return new SecurityConfiguration 105 | ("client", "secret", "", "", "Bearer access token", ApiKeyVehicle.HEADER, HttpHeaders.AUTHORIZATION,""); 106 | } 107 | 108 | 109 | /** 110 | * 111 | * @return ApiInf 112 | */ 113 | private ApiInfo apiInfo() { 114 | return new ApiInfoBuilder().title("Authentication API").description("") 115 | .termsOfServiceUrl("https://www.example.com/api") 116 | .contact(new Contact("Developers", "https://projects.spring.io/spring-boot/", "")) 117 | .license("Open Source") 118 | .licenseUrl("\"https://www.apache.org/licenses/LICENSE-2.0") 119 | .version("1.0.0") 120 | .build(); 121 | 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.authentication.config; 2 | 3 | import org.springframework.boot.autoconfigure.security.SecurityProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.annotation.Order; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 10 | 11 | 12 | /** 13 | * @author Rohit.Kumar 14 | */ 15 | @Configuration 16 | @EnableWebSecurity(debug = true) 17 | @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 18 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 19 | 20 | 21 | @Bean 22 | @Override 23 | public AuthenticationManager authenticationManagerBean() throws Exception { 24 | return super.authenticationManagerBean(); 25 | } 26 | 27 | 28 | } -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/config/package-info.java: -------------------------------------------------------------------------------- 1 | package com.authentication.config; 2 | /* 3 | This Package contains all configuration classed related security micro-service. 4 | */ -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/model/User.java: -------------------------------------------------------------------------------- 1 | package com.authentication.model; 2 | 3 | import io.swagger.annotations.ApiModelProperty; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | 7 | import javax.persistence.*; 8 | import java.time.LocalDateTime; 9 | import java.util.ArrayList; 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | 14 | /** 15 | * @author Rohit.Kumar 16 | */ 17 | @Entity 18 | @Table(name = "users") 19 | public class User implements UserDetails { 20 | 21 | static final long serialVersionUID = 1L; 22 | 23 | @Id 24 | @GeneratedValue(strategy = GenerationType.AUTO) 25 | @Column(name = "user_id", nullable = false, updatable = false) 26 | @ApiModelProperty(notes = "The database generated user, token and session mapping ID.") 27 | private Long id; 28 | 29 | @Column(name = "username", nullable = false, unique = true) 30 | @ApiModelProperty(notes = "user name") 31 | private String username; 32 | 33 | @Column(name = "password", nullable = false) 34 | @ApiModelProperty(notes = "User password") 35 | private String password; 36 | 37 | @Column(name = "enabled", nullable = false) 38 | @ApiModelProperty(notes = "Indicates whether the user is enabled or disabled. A disabled user cannot be authenticated.") 39 | private boolean enabled; 40 | 41 | @Column(name = "created_time", insertable=true, updatable=false) 42 | @ApiModelProperty(notes = "The database generated user, token and session mapping created time.") 43 | private LocalDateTime createdTime; 44 | 45 | @Column(name = "updated_time", insertable=false, updatable=true) 46 | @ApiModelProperty(notes = "The database generated user, token and session mapping updated time.") 47 | private LocalDateTime updatedTime; 48 | 49 | @PrePersist 50 | protected void onCreate() { 51 | createdTime = LocalDateTime.now(); 52 | updatedTime = LocalDateTime.now(); 53 | } 54 | 55 | @PreUpdate 56 | protected void onUpdate() { 57 | updatedTime = LocalDateTime.now(); 58 | } 59 | 60 | 61 | @Override 62 | public Collection getAuthorities() { 63 | List authorities = new ArrayList(); 64 | 65 | return authorities; 66 | } 67 | 68 | @Override 69 | public boolean isAccountNonExpired() { 70 | return true; 71 | } 72 | 73 | @Override 74 | public boolean isAccountNonLocked() { 75 | return true; 76 | } 77 | 78 | @Override 79 | public boolean isCredentialsNonExpired() { 80 | return true; 81 | } 82 | 83 | @Override 84 | public boolean isEnabled() { 85 | return enabled; 86 | } 87 | 88 | @Override 89 | public String getPassword() { 90 | return password; 91 | } 92 | 93 | @Override 94 | public String getUsername() { 95 | return username; 96 | } 97 | 98 | public Long getId() { 99 | return id; 100 | } 101 | 102 | public LocalDateTime getCreatedTime() { 103 | return createdTime; 104 | } 105 | 106 | public LocalDateTime getUpdatedTime() { 107 | return updatedTime; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/model/UserTokenSession.java: -------------------------------------------------------------------------------- 1 | package com.authentication.model; 2 | 3 | 4 | import io.swagger.annotations.ApiModelProperty; 5 | 6 | import javax.persistence.*; 7 | import java.time.LocalDateTime; 8 | import java.util.Objects; 9 | 10 | 11 | /** 12 | * @author Rohit.Kumar 13 | */ 14 | @Entity 15 | @Table(name = "tbl_user_token_session") 16 | public class UserTokenSession { 17 | 18 | static final long serialVersionUID = 1L; 19 | 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.AUTO) 22 | @Column(name = "id", nullable = false, updatable = false) 23 | @ApiModelProperty(notes = "The database generated user, token and session mapping ID.") 24 | private Long id; 25 | 26 | @Column(name = "username", nullable = false, unique = true) 27 | @ApiModelProperty(notes = "user name.") 28 | private String username; 29 | 30 | @Column(name = "token", nullable = false, unique = true, length = 500) 31 | @ApiModelProperty(notes = "Authorization token.") 32 | private String token; 33 | 34 | @Column(name = "session_id", nullable = false, unique = true) 35 | @ApiModelProperty(notes = "Session-id received in request header.") 36 | private String sessionId; 37 | 38 | @Column(name = "expiry_time", nullable = false) 39 | @ApiModelProperty(notes = "Authorization token expiry time.") 40 | private Long expiryTime; 41 | 42 | @Column(name = "created_time", insertable=true, updatable=false) 43 | @ApiModelProperty(notes = "The database generated user, token and session mapping created time.") 44 | private LocalDateTime createdTime; 45 | 46 | @Column(name = "updated_time", insertable=false, updatable=true) 47 | @ApiModelProperty(notes = "The database generated user, token and session mapping updated time.") 48 | private LocalDateTime updatedTime; 49 | 50 | @PrePersist 51 | protected void onCreate() { 52 | createdTime = LocalDateTime.now(); 53 | updatedTime = LocalDateTime.now(); 54 | } 55 | 56 | @PreUpdate 57 | protected void onUpdate() { 58 | updatedTime = LocalDateTime.now(); 59 | } 60 | 61 | public UserTokenSession() { 62 | } 63 | 64 | public UserTokenSession(String username, String token, String sessionId, Long expiryTime) { 65 | this.username = username; 66 | this.token = token; 67 | this.sessionId = sessionId; 68 | this.expiryTime = expiryTime; 69 | } 70 | 71 | public Long getId() { 72 | return id; 73 | } 74 | 75 | public String getUsername() { 76 | return username; 77 | } 78 | 79 | public String getToken() { 80 | return token; 81 | } 82 | 83 | public String getSessionId() { 84 | return sessionId; 85 | } 86 | 87 | public Long getExpiryTime() { 88 | return expiryTime; 89 | } 90 | 91 | public LocalDateTime getCreatedTime() { 92 | return createdTime; 93 | } 94 | 95 | public LocalDateTime getUpdatedTime() { 96 | return updatedTime; 97 | } 98 | 99 | @Override 100 | public boolean equals(Object o) { 101 | if (this == o) return true; 102 | if (o == null || getClass() != o.getClass()) return false; 103 | UserTokenSession that = (UserTokenSession) o; 104 | return Objects.equals(username, that.username) && 105 | Objects.equals(token, that.token) && 106 | Objects.equals(sessionId, that.sessionId) && 107 | Objects.equals(expiryTime, that.expiryTime); 108 | } 109 | 110 | @Override 111 | public int hashCode() { 112 | 113 | return Objects.hash(username, token, sessionId, expiryTime); 114 | } 115 | 116 | @Override 117 | public String toString() { 118 | return "UserTokenSession{" + 119 | "id=" + id + 120 | ", username='" + username + '\'' + 121 | ", token='" + token + '\'' + 122 | ", sessionId='" + sessionId + '\'' + 123 | ", expiryTime=" + expiryTime + 124 | ", createdTime=" + createdTime + 125 | ", updatedTime=" + updatedTime + 126 | '}'; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.authentication.repository; 2 | 3 | import com.authentication.model.User; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Rohit.Kumar 9 | */ 10 | @Repository 11 | public interface UserRepository extends JpaRepository { 12 | 13 | /** 14 | * 15 | * @param username 16 | * @return @{@link User} 17 | */ 18 | User findOneByUsername(String username); 19 | } 20 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/repository/UserTokenSessionRepository.java: -------------------------------------------------------------------------------- 1 | package com.authentication.repository; 2 | 3 | import com.authentication.model.UserTokenSession; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Rohit.Kumar 9 | */ 10 | @Repository 11 | public interface UserTokenSessionRepository extends CrudRepository { 12 | 13 | /** 14 | * Find {@link UserTokenSession} for the given username. 15 | * @param username 16 | * @return @{@link UserTokenSession} 17 | */ 18 | UserTokenSession findOneByUsername(String username); 19 | 20 | } -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/service/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.authentication.service; 2 | 3 | import com.authentication.model.User; 4 | import com.authentication.repository.UserRepository; 5 | import org.apache.log4j.Logger; 6 | import org.springframework.beans.factory.annotation.Autowired; 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 | 12 | /** 13 | * @author Rohit.Kumar 14 | */ 15 | @Service("userDetailsService") 16 | public class UserDetailsServiceImpl implements UserDetailsService { 17 | 18 | private static final Logger LOGGER = Logger.getLogger(UserDetailsServiceImpl.class); 19 | 20 | @Autowired 21 | private UserRepository userRepository; 22 | 23 | @Override 24 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 25 | 26 | User userFromDataBase = userRepository.findOneByUsername(username); 27 | if (userFromDataBase == null) { 28 | LOGGER.info("User " + username + " was not found in the database"); 29 | throw new UsernameNotFoundException("User " + username + " was not found in the database"); 30 | } 31 | return userFromDataBase; 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/service/UserTokenSessionService.java: -------------------------------------------------------------------------------- 1 | package com.authentication.service; 2 | 3 | import com.authentication.model.UserTokenSession; 4 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 5 | 6 | /** 7 | * @author Rohit.Kumar 8 | */ 9 | public interface UserTokenSessionService { 10 | 11 | /** 12 | * Check whether there is mapping between oauth token, username and session-id. 13 | * And the token is not yet expired. 14 | * @param userTokenSession 15 | * @return ValidMappingResponse if valid mapping else throw {@link UsernameNotFoundException} 16 | */ 17 | ValidMappingResponse isValidUserTokenSessionMapping(UserTokenSession userTokenSession) throws UsernameNotFoundException; 18 | 19 | /** 20 | * 21 | * @param userTokenSession 22 | * @return token session record from data base. 23 | */ 24 | UserTokenSession saveUserTokenSessionMapping(UserTokenSession userTokenSession); 25 | 26 | 27 | /** 28 | * Class to store isValidUserTokenSessionMapping() response. 29 | */ 30 | class ValidMappingResponse { 31 | 32 | private boolean valid; 33 | private UserTokenSession userTokenSession; 34 | 35 | public ValidMappingResponse() { 36 | } 37 | 38 | public ValidMappingResponse(boolean valid, UserTokenSession userTokenSession ) { 39 | this.valid = valid; 40 | this.userTokenSession = userTokenSession; 41 | } 42 | 43 | public boolean isValid() { 44 | return valid; 45 | } 46 | 47 | public void setValid(boolean valid) { 48 | this.valid = valid; 49 | } 50 | 51 | public UserTokenSession getUserTokenSession() { 52 | return userTokenSession; 53 | } 54 | 55 | public void setUserTokenSession(UserTokenSession userTokenSession) { 56 | this.userTokenSession = userTokenSession; 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /authentication/src/main/java/com/authentication/service/UserTokenSessionServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.authentication.service; 2 | 3 | import com.authentication.model.UserTokenSession; 4 | import com.authentication.repository.UserTokenSessionRepository; 5 | import org.apache.log4j.Logger; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.time.LocalDateTime; 11 | import java.time.ZoneId; 12 | import java.time.ZonedDateTime; 13 | import java.util.Objects; 14 | 15 | /** 16 | * @author Rohit.Kumar 17 | */ 18 | @Service 19 | public class UserTokenSessionServiceImpl implements UserTokenSessionService { 20 | 21 | private static final Logger LOGGER = Logger.getLogger(UserTokenSessionServiceImpl.class); 22 | 23 | @Autowired 24 | private UserTokenSessionRepository userTokenSessionRepository; 25 | 26 | 27 | @Override 28 | public ValidMappingResponse isValidUserTokenSessionMapping(UserTokenSession userTokenSession) throws UsernameNotFoundException { 29 | 30 | String username = userTokenSession.getUsername(); 31 | UserTokenSession userTokenSessionFromDB = userTokenSessionRepository.findOneByUsername(username); 32 | 33 | if (Objects.isNull(userTokenSessionFromDB)) { 34 | 35 | LOGGER.error("User " + username + " mapping with token is not found in the database."); 36 | throw new UsernameNotFoundException("User " + username + " mapping with token is not found in the database."); 37 | } 38 | 39 | /** 40 | * TODO Time zone of data base and client may be different. 41 | */ 42 | LocalDateTime currentSystemTime = LocalDateTime.now(); 43 | ZonedDateTime currentZonedDateTime = currentSystemTime.atZone(ZoneId.systemDefault()); 44 | long currentTimeInMillis = currentZonedDateTime.toInstant().toEpochMilli(); 45 | 46 | ZonedDateTime dataBaseZonedDateTime = userTokenSessionFromDB.getCreatedTime().atZone(ZoneId.systemDefault()); 47 | 48 | /** 49 | * tokenTimeInMillis = created_time in millis + expiry time (seconds) * 1000. 50 | */ 51 | long tokenTimeInMillis = dataBaseZonedDateTime.toInstant().toEpochMilli() + (userTokenSessionFromDB.getExpiryTime() * 1000); 52 | 53 | if ( currentTimeInMillis >= tokenTimeInMillis) { 54 | 55 | LOGGER.info("User " + username + " token has expired. Please generate new token. Deleting the expired token mapping."); 56 | userTokenSessionRepository.delete(userTokenSessionFromDB); 57 | throw new UsernameNotFoundException("User " + username + " token has expired. Please generate new token."); 58 | 59 | }else if(!userTokenSession.equals(userTokenSessionFromDB)) { 60 | 61 | if (!userTokenSessionFromDB.getToken().equals(userTokenSession.getToken())){ 62 | LOGGER.info("User "+userTokenSession.getUsername()+ " has invalid user and token mapping. Please generate new token."); 63 | 64 | } else { 65 | LOGGER.info("User "+userTokenSession.getUsername()+ " has invalid user and session-id mapping. Please generate new token."); 66 | } 67 | 68 | LOGGER.info("So, Deleting the invalid mapping."); 69 | userTokenSessionRepository.delete(userTokenSessionFromDB); 70 | throw new UsernameNotFoundException("User " + username + " has invalid user, session-id and token mapping. Please generate new token."); 71 | 72 | }else { 73 | 74 | LOGGER.info("User " + username + " has valid token."); 75 | ValidMappingResponse validMappingResponse = new ValidMappingResponse(true, userTokenSessionFromDB); 76 | return validMappingResponse; 77 | } 78 | 79 | } 80 | 81 | @Override 82 | public UserTokenSession saveUserTokenSessionMapping(UserTokenSession userTokenSession) { 83 | 84 | UserTokenSession userTokenSessionFromDB = userTokenSessionRepository.findOneByUsername(userTokenSession.getUsername()); 85 | 86 | /** 87 | * 1. If User is making the login call again with the same session-id and token. Then delete the old mapping and return the new inserted mapping. 88 | * 2. If same user is making login call with the new token or session-id. Then delete the old mapping and return the new inserted mapping 89 | */ 90 | if (Objects.nonNull(userTokenSessionFromDB)) { 91 | 92 | if (userTokenSessionFromDB.equals(userTokenSession)) { 93 | LOGGER.info("User "+userTokenSession.getUsername()+ " making login call again with same token and session-id."); 94 | 95 | } else if (!userTokenSessionFromDB.getToken().equals(userTokenSession.getToken())){ 96 | LOGGER.info("User "+userTokenSession.getUsername()+ " making login call with new token"); 97 | 98 | } else { 99 | LOGGER.info("User "+userTokenSession.getUsername()+ " making login call with different session-id"); 100 | 101 | } 102 | LOGGER.info("So, Deleting older mapping from tbl_user_token_session."+userTokenSessionFromDB); 103 | userTokenSessionRepository.delete(userTokenSessionFromDB); 104 | 105 | } 106 | 107 | return userTokenSessionRepository.save(userTokenSession); 108 | } 109 | 110 | 111 | 112 | } 113 | -------------------------------------------------------------------------------- /authentication/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | server.contextPath=/api 3 | 4 | logging.level.com.alfred=DEBUG 5 | 6 | # Data source properties 7 | spring.jpa.hibernate.ddl-auto=validate 8 | spring.jpa.show-sql=true 9 | 10 | # openssl genrsa -out jwt.pem 2048 11 | # openssl rsa -in jwt.pem 12 | config.oauth2.privateKey=MIICXQIBAAKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQABAoGAImnYGU3ApPOVtBf/TOqLfne+2SZX96eVU06myDY3zA4rO3DfbR7CzCLE6qPnyDAIiW0UQBs0oBDdWOnOqz5YaePZu/yrLyj6KM6Q2e9ywRDtDh3ywrSfGpjdSvvoaeL1WesBWsgWv1vFKKvES7ILFLUxKwyCRC2Lgh7aI9GGZfECQQD84m98Yrehhin3fZuRaBNIu348Ci7ZFZmrvyxAIxrV4jBjpACW0RM2BvF5oYM2gOJqIfBOVjmPwUrobYEFcHRvAkEAz8jsfmxsZVwh3Y/Y47BzhKIC5FLaads541jNjVWfrPirljyCy1n4sg3WQH2IEyap3WTP84+csCtsfNfyK7fQdwJBAJNRyobY74cupJYkW5OK4OkXKQQLHp2iosJV/Y5jpQeC3JO/gARcSmfIBbbI66q9zKjtmpPYUXI4tc3PtUEY8QsCQQCcxySyC0sKe6bNzyC+Q8AVvkxiTKWiI5idEr8duhJd589H72Zc2wkMB+a2CEGo+Y5Hjy5cvuph/pG/7Qw7sljnAkAy/feClt1mUEiAcWrHRwcQ71AoA0+21yC9VkqPNrn3w7OEg8gBqPjRlXBNb00QieNeGGSkXOoU6gFschR22Dzy 13 | 14 | # openssl rsa -in jwt.pem -pubout 15 | config.oauth2.publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQAB 16 | 17 | 18 | #oauth configurations 19 | config.oauth2.tokenTimeout=3600 20 | config.oauth2.resource.id=oauth2-resource 21 | config.oauth2.clientID=client 22 | config.oauth2.clientSecret=secret 23 | security.oauth2.client.grantType=client_credentials 24 | config.oauth2.accessTokenUri=http://localhost:8080/api/oauth/token 25 | config.oauth2.userAuthorizationUri=http://localhost:8080/api/oauth/authorize 26 | config.oauth2.resourceURI= http://localhost:8080/api/oauth/authorize 27 | -------------------------------------------------------------------------------- /authentication/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO users (user_id, username, password, enabled) VALUES 2 | ('1', 'user1@example.com', '$2a$10$D4OLKI6yy68crm.3imC9X.P2xqKHs5TloWUcr6z5XdOqnTrAK84ri', true), 3 | ('2', 'user2@example.com', '$2a$10$D4OLKI6yy68crm.3imC9X.P2xqKHs5TloWUcr6z5XdOqnTrAK84ri', true), 4 | ('3', 'user3@example.com', '$2a$10$D4OLKI6yy68crm.3imC9X.P2xqKHs5TloWUcr6z5XdOqnTrAK84ri', true); 5 | 6 | -------------------------------------------------------------------------------- /authentication/src/main/resources/images/Swagger-UI-Home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrohitramsen/spring-boot-oauth2-jwt-swagger-ui/97fa9a3063bf4367aa572a5c102295104ee9208e/authentication/src/main/resources/images/Swagger-UI-Home.png -------------------------------------------------------------------------------- /authentication/src/main/resources/images/Swagger-ui-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrohitramsen/spring-boot-oauth2-jwt-swagger-ui/97fa9a3063bf4367aa572a5c102295104ee9208e/authentication/src/main/resources/images/Swagger-ui-auth.png -------------------------------------------------------------------------------- /authentication/src/main/resources/images/swagger-ui-login-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrohitramsen/spring-boot-oauth2-jwt-swagger-ui/97fa9a3063bf4367aa572a5c102295104ee9208e/authentication/src/main/resources/images/swagger-ui-login-token.png -------------------------------------------------------------------------------- /authentication/src/main/resources/images/swagger-ui-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrohitramsen/spring-boot-oauth2-jwt-swagger-ui/97fa9a3063bf4367aa572a5c102295104ee9208e/authentication/src/main/resources/images/swagger-ui-login.png -------------------------------------------------------------------------------- /authentication/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS users; 2 | CREATE TABLE users ( 3 | user_id BIGINT PRIMARY KEY auto_increment, 4 | username VARCHAR(128) UNIQUE, 5 | password VARCHAR(256), 6 | enabled BOOL 7 | ); 8 | 9 | -------------------------------------------------------------------------------- /authentication/src/test/java/com/authentication/api/AuthenticationAPITest.java: -------------------------------------------------------------------------------- 1 | package com.authentication.api; 2 | 3 | import com.authentication.model.UserTokenSession; 4 | import com.authentication.service.UserDetailsServiceImpl; 5 | import com.authentication.service.UserTokenSessionService; 6 | import com.authentication.service.UserTokenSessionServiceImpl; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mockito.InjectMocks; 11 | import org.mockito.Mockito; 12 | import org.mockito.MockitoAnnotations; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.http.HttpHeaders; 17 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 18 | import org.springframework.security.core.Authentication; 19 | import org.springframework.security.core.userdetails.UserDetailsService; 20 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 21 | import org.springframework.security.oauth2.provider.OAuth2Request; 22 | import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; 23 | import org.springframework.test.context.junit4.SpringRunner; 24 | import org.springframework.test.context.web.WebAppConfiguration; 25 | import org.springframework.test.web.servlet.MockMvc; 26 | import org.springframework.test.web.servlet.request.RequestPostProcessor; 27 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 28 | import org.springframework.util.ReflectionUtils; 29 | 30 | import javax.servlet.http.HttpServletRequest; 31 | import java.io.IOException; 32 | import java.lang.reflect.Field; 33 | 34 | import static org.mockito.Matchers.any; 35 | 36 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 37 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 38 | 39 | /** 40 | * @implNote This class provide Junits for {@link AuthenticationAPI} class. 41 | * @author Rohit.Kumar 42 | * 43 | */ 44 | @RunWith(SpringRunner.class) 45 | @WebAppConfiguration 46 | @SpringBootTest 47 | public class AuthenticationAPITest { 48 | 49 | @InjectMocks 50 | private AuthenticationAPI authenticationAPI; 51 | 52 | private MockMvc mockMvc; 53 | private UserDetailsService userDetailsService; 54 | private UserTokenSessionServiceImpl userTokenSessionService; 55 | 56 | @Value("${config.oauth2.tokenTimeout}") 57 | private String tokenExpiryTime; 58 | 59 | 60 | @Autowired 61 | private OAuthHelper oAuthHelper; 62 | 63 | private RequestPostProcessor requestPostProcessor; 64 | private UserTokenSession userTokenSession; 65 | private HttpHeaders httpHeaders; 66 | private OAuth2Authentication oAuth2Authentication; 67 | 68 | @Before 69 | public void setup() throws IOException { 70 | 71 | MockitoAnnotations.initMocks(this); 72 | userDetailsService = Mockito.mock(UserDetailsServiceImpl.class); 73 | userTokenSessionService = Mockito.mock(UserTokenSessionServiceImpl.class); 74 | Field field = ReflectionUtils.findField(AuthenticationAPI.class, "userDetailsService"); 75 | ReflectionUtils.makeAccessible(field); 76 | ReflectionUtils.setField(field, authenticationAPI, userDetailsService); 77 | 78 | field = ReflectionUtils.findField(AuthenticationAPI.class, "userTokenSessionService"); 79 | ReflectionUtils.makeAccessible(field); 80 | ReflectionUtils.setField(field, authenticationAPI, userTokenSessionService); 81 | 82 | this.mockMvc = MockMvcBuilders.standaloneSetup(authenticationAPI).build(); 83 | 84 | 85 | /** 86 | * testLogin and testValidateToken Set-up 87 | */ 88 | 89 | String username = "user"; 90 | String password = "password"; 91 | 92 | requestPostProcessor = oAuthHelper.addBearerToken(username, password); 93 | Authentication authentication = new UsernamePasswordAuthenticationToken(username, password); 94 | OAuth2Request oAuth2Request = oAuthHelper.createOAuth2Request(username, password); 95 | oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication); 96 | HttpServletRequest httpServletRequest = oAuthHelper.buildMockHttpServletRequest(username, password); 97 | OAuth2AuthenticationDetails oAuth2AuthenticationDetails = new OAuth2AuthenticationDetails(httpServletRequest); 98 | oAuth2Authentication.setDetails(oAuth2AuthenticationDetails); 99 | 100 | userTokenSession = new UserTokenSession(username, httpServletRequest.getHeader("Authorization"), "JSESSION : Test-123", Long.valueOf(tokenExpiryTime)); 101 | 102 | httpHeaders = new HttpHeaders(); 103 | httpHeaders.add("Authorization", httpServletRequest.getHeader("Authorization")); 104 | httpHeaders.add("cookie", "JSESSION : Test-123"); 105 | } 106 | 107 | 108 | 109 | @Test 110 | public void testValidateToken() throws Exception { 111 | 112 | UserTokenSessionService.ValidMappingResponse expectedValidMappingResponse = new UserTokenSessionService.ValidMappingResponse(true, userTokenSession); 113 | Mockito.when(userTokenSessionService.isValidUserTokenSessionMapping(any())).thenReturn(expectedValidMappingResponse); 114 | 115 | this.mockMvc.perform(post("/oauth/validateToken").with(requestPostProcessor).principal(oAuth2Authentication).headers(httpHeaders)) 116 | .andExpect(status().is(200)) 117 | .equals(userTokenSession); 118 | } 119 | 120 | @Test 121 | public void testLogin() throws Exception { 122 | 123 | Mockito.when(userTokenSessionService.saveUserTokenSessionMapping(any())).thenReturn(userTokenSession); 124 | 125 | this.mockMvc.perform(post("/oauth/login").with(requestPostProcessor).principal(oAuth2Authentication).headers(httpHeaders)) 126 | .andExpect(status().is(200)) 127 | .equals(userTokenSession); 128 | } 129 | 130 | 131 | } 132 | -------------------------------------------------------------------------------- /authentication/src/test/java/com/authentication/api/OAuthHelper.java: -------------------------------------------------------------------------------- 1 | package com.authentication.api; 2 | 3 | import com.authentication.api.AuthenticationAPI; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.mock.web.MockHttpServletRequest; 7 | import org.springframework.mock.web.MockHttpSession; 8 | import org.springframework.security.authentication.TestingAuthenticationToken; 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 11 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 12 | import org.springframework.security.oauth2.provider.OAuth2Request; 13 | import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.test.web.servlet.request.RequestPostProcessor; 16 | 17 | import javax.servlet.http.HttpServletRequest; 18 | import java.util.HashMap; 19 | import java.util.HashSet; 20 | import java.util.Map; 21 | import java.util.Set; 22 | 23 | /** 24 | * Helper class for creating OAuth access token, OAuth Authentication, {@link MockHttpServletRequest} objects. 25 | */ 26 | @Component 27 | public class OAuthHelper { 28 | 29 | 30 | @Value("${config.oauth2.clientID}") 31 | private String clientID; 32 | 33 | @Value("${config.oauth2.clientSecret}") 34 | private String clientSecret; 35 | 36 | @Value("${config.oauth2.resource.id}") 37 | private String resourceId; 38 | 39 | @Autowired 40 | private AuthorizationServerTokenServices tokenservice; 41 | 42 | /** 43 | * Create {@link RequestPostProcessor} for {@link AuthenticationAPI} testing. 44 | * @param username 45 | * @param password 46 | * @return 47 | */ 48 | public RequestPostProcessor addBearerToken(final String username, String password) { 49 | 50 | RequestPostProcessor requestPostProcessor = new RequestPostProcessor() { 51 | @Override 52 | public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { 53 | 54 | OAuth2Request oauth2Request = createOAuth2Request(username, password); 55 | Authentication userauth = new TestingAuthenticationToken(username, password); 56 | OAuth2Authentication oauth2auth = new OAuth2Authentication(oauth2Request, userauth); 57 | OAuth2AccessToken oAuth2AccessToken = tokenservice.createAccessToken(oauth2auth); 58 | 59 | request.addHeader("Authorization", "Bearer " + oAuth2AccessToken.getValue()); 60 | request.setSession(new MockHttpSession()); 61 | return request; 62 | } 63 | }; 64 | return requestPostProcessor; 65 | } 66 | 67 | /** 68 | * Build {@link MockHttpServletRequest} for the given user with {@link OAuth2AccessToken}. 69 | * @param username 70 | * @param password 71 | * @return HttpServletRequest 72 | */ 73 | public HttpServletRequest buildMockHttpServletRequest(final String username, String password) { 74 | 75 | MockHttpServletRequest httpServletRequest = new MockHttpServletRequest();//Mockito.mock(MockHttpServletRequest.class); 76 | OAuth2Request oauth2Request = createOAuth2Request(username, password); 77 | Authentication userauth = new TestingAuthenticationToken(username, password); 78 | OAuth2Authentication oauth2auth = new OAuth2Authentication(oauth2Request, userauth); 79 | OAuth2AccessToken oAuth2AccessToken = tokenservice.createAccessToken(oauth2auth); 80 | 81 | httpServletRequest.addHeader("Authorization", "Bearer " + oAuth2AccessToken.getValue()); 82 | httpServletRequest.setSession(new MockHttpSession()); 83 | return httpServletRequest; 84 | } 85 | 86 | /** 87 | * Create {@link OAuth2Request} 88 | * @param username 89 | * @param password 90 | * @return OAuth2Request 91 | */ 92 | public OAuth2Request createOAuth2Request(String username, String password) { 93 | 94 | Map requestParams = new HashMap<>(); 95 | requestParams.put("username", username); 96 | requestParams.put("password", password); 97 | requestParams.put("grant_type", "password"); 98 | requestParams.put("client_id", clientID); 99 | requestParams.put("client_secret", clientSecret); 100 | 101 | Set scope = new HashSet<>(); 102 | scope.add("read"); 103 | scope.add("write"); 104 | 105 | Set resourceIds = new HashSet<>(); 106 | resourceIds.add(resourceId); 107 | 108 | OAuth2Request oauth2Request = new OAuth2Request(requestParams, clientID, null, true, scope, resourceIds, null, null, null); 109 | 110 | return oauth2Request; 111 | } 112 | 113 | 114 | } -------------------------------------------------------------------------------- /authentication/src/test/java/com/authentication/service/UserDetailsServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.authentication.service; 2 | 3 | import com.authentication.api.OAuthHelper; 4 | import com.authentication.model.User; 5 | import com.authentication.repository.UserRepository; 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mockito.InjectMocks; 11 | import org.mockito.Mockito; 12 | import org.mockito.MockitoAnnotations; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.test.context.junit4.SpringRunner; 17 | import org.springframework.test.context.web.WebAppConfiguration; 18 | import org.springframework.util.ReflectionUtils; 19 | 20 | import java.io.IOException; 21 | import java.lang.reflect.Field; 22 | 23 | /** 24 | * @implNote This class provide Junits for {@link UserDetailsServiceImpl} class. 25 | * @author Rohit.Kumar 26 | * 27 | */ 28 | @RunWith(SpringRunner.class) 29 | @WebAppConfiguration 30 | @SpringBootTest 31 | public class UserDetailsServiceTest { 32 | 33 | @InjectMocks 34 | private UserDetailsServiceImpl userDetailsService; 35 | 36 | private UserRepository userRepository; 37 | 38 | @Autowired 39 | private OAuthHelper oAuthHelper; 40 | 41 | @Value("${config.oauth2.tokenTimeout}") 42 | private String tokenExpiryTime; 43 | 44 | private User user; 45 | 46 | @Before 47 | public void setup() throws IOException { 48 | 49 | MockitoAnnotations.initMocks(this); 50 | userRepository = Mockito.mock(UserRepository.class); 51 | 52 | Field field = ReflectionUtils.findField(UserDetailsServiceImpl.class, "userRepository"); 53 | ReflectionUtils.makeAccessible(field); 54 | ReflectionUtils.setField(field, userDetailsService, userRepository); 55 | 56 | user = Mockito.mock(User.class); 57 | } 58 | 59 | @Test 60 | public void testLoadUserByUsername() { 61 | 62 | String username = "dumy_user"; 63 | Mockito.when(userRepository.findOneByUsername(username)).thenReturn(user); 64 | 65 | Assert.assertEquals(userDetailsService.loadUserByUsername(username), user); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /authentication/src/test/java/com/authentication/service/UserTokenSessionServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.authentication.service; 2 | 3 | import com.authentication.api.OAuthHelper; 4 | import com.authentication.model.UserTokenSession; 5 | import com.authentication.repository.UserTokenSessionRepository; 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mockito.InjectMocks; 11 | import org.mockito.Mockito; 12 | import org.mockito.MockitoAnnotations; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 17 | import org.springframework.test.context.junit4.SpringRunner; 18 | import org.springframework.test.context.web.WebAppConfiguration; 19 | import org.springframework.util.ReflectionUtils; 20 | 21 | import javax.servlet.http.HttpServletRequest; 22 | import java.io.IOException; 23 | import java.lang.reflect.Field; 24 | import java.time.LocalDateTime; 25 | 26 | import static org.mockito.Matchers.any; 27 | 28 | /** 29 | * @implNote This class provide Junits for {@link UserTokenSessionServiceImpl} class. 30 | * @author Rohit.Kumar 31 | * 32 | */ 33 | @RunWith(SpringRunner.class) 34 | @WebAppConfiguration 35 | @SpringBootTest 36 | public class UserTokenSessionServiceTest { 37 | 38 | private UserTokenSessionRepository userTokenSessionRepository; 39 | 40 | @InjectMocks 41 | private UserTokenSessionServiceImpl userTokenSessionService; 42 | 43 | @Autowired 44 | private OAuthHelper oAuthHelper; 45 | 46 | @Value("${config.oauth2.tokenTimeout}") 47 | private String tokenExpiryTime; 48 | private UserTokenSession userTokenSession; 49 | 50 | @Before 51 | public void setup() throws IOException { 52 | 53 | MockitoAnnotations.initMocks(this); 54 | userTokenSessionRepository = Mockito.mock(UserTokenSessionRepository.class); 55 | Field field = ReflectionUtils.findField(UserTokenSessionServiceImpl.class, "userTokenSessionRepository"); 56 | ReflectionUtils.makeAccessible(field); 57 | ReflectionUtils.setField(field, userTokenSessionService, userTokenSessionRepository); 58 | 59 | /** 60 | * testIsValidUserTokenSessionMapping and testSaveUserTokenSessionMapping Set-up 61 | */ 62 | 63 | String username = "user"; 64 | String password = "password"; 65 | HttpServletRequest httpServletRequest = oAuthHelper.buildMockHttpServletRequest(username, password); 66 | userTokenSession = new UserTokenSession(username, httpServletRequest.getHeader("Authorization"), "JSESSION : Test-123", Long.valueOf(tokenExpiryTime)); 67 | } 68 | 69 | @Test(expected = UsernameNotFoundException.class) 70 | public void testIsValidUserTokenSessionMapping() { 71 | 72 | UserTokenSession mockUserTokenSession = Mockito.spy(userTokenSession); 73 | Mockito.when(userTokenSessionRepository.findOneByUsername(userTokenSession.getUsername())).thenReturn(mockUserTokenSession); 74 | Mockito.when(mockUserTokenSession.getCreatedTime()).thenReturn( LocalDateTime.now().plusDays(2)); 75 | 76 | userTokenSessionService.isValidUserTokenSessionMapping(userTokenSession); 77 | 78 | } 79 | 80 | @Test 81 | public void testSaveUserTokenSessionMapping() { 82 | 83 | Mockito.when(userTokenSessionRepository.save(any(UserTokenSession.class))).thenReturn(userTokenSession); 84 | Assert.assertEquals(userTokenSessionService.saveUserTokenSessionMapping(userTokenSession), userTokenSession); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /authentication/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | server.contextPath=/authenticateService 3 | 4 | logging.level.com.alfred=DEBUG 5 | 6 | # Data source properties 7 | spring.jpa.hibernate.ddl-auto=validate 8 | spring.jpa.show-sql=true 9 | 10 | # openssl genrsa -out jwt.pem 2048 11 | # openssl rsa -in jwt.pem 12 | config.oauth2.privateKey=MIICXQIBAAKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQABAoGAImnYGU3ApPOVtBf/TOqLfne+2SZX96eVU06myDY3zA4rO3DfbR7CzCLE6qPnyDAIiW0UQBs0oBDdWOnOqz5YaePZu/yrLyj6KM6Q2e9ywRDtDh3ywrSfGpjdSvvoaeL1WesBWsgWv1vFKKvES7ILFLUxKwyCRC2Lgh7aI9GGZfECQQD84m98Yrehhin3fZuRaBNIu348Ci7ZFZmrvyxAIxrV4jBjpACW0RM2BvF5oYM2gOJqIfBOVjmPwUrobYEFcHRvAkEAz8jsfmxsZVwh3Y/Y47BzhKIC5FLaads541jNjVWfrPirljyCy1n4sg3WQH2IEyap3WTP84+csCtsfNfyK7fQdwJBAJNRyobY74cupJYkW5OK4OkXKQQLHp2iosJV/Y5jpQeC3JO/gARcSmfIBbbI66q9zKjtmpPYUXI4tc3PtUEY8QsCQQCcxySyC0sKe6bNzyC+Q8AVvkxiTKWiI5idEr8duhJd589H72Zc2wkMB+a2CEGo+Y5Hjy5cvuph/pG/7Qw7sljnAkAy/feClt1mUEiAcWrHRwcQ71AoA0+21yC9VkqPNrn3w7OEg8gBqPjRlXBNb00QieNeGGSkXOoU6gFschR22Dzy 13 | 14 | # openssl rsa -in jwt.pem -pubout 15 | config.oauth2.publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNQZKqTlO/+2b4ZdhqGJzGBDltb5PZmBz1ALN2YLvt341pH6i5mO1V9cX5Ty1LM70fKfnIoYUP4KCE33dPnC7LkUwE/myh1zM6m8cbL5cYFPyP099thbVxzJkjHWqywvQih/qOOjliomKbM9pxG8Z1dB26hL9dSAZuA8xExjlPmQIDAQAB 16 | 17 | 18 | #oauth configurations 19 | config.oauth2.tokenTimeout=3600 20 | config.oauth2.resource.id=oauth2-resource 21 | config.oauth2.clientID=client 22 | config.oauth2.clientSecret=secret 23 | security.oauth2.client.grantType=client_credentials 24 | config.oauth2.accessTokenUri=http://localhost:8080/authenticateService/oauth/token 25 | config.oauth2.userAuthorizationUri=http://localhost:8080/authenticateService/oauth/authorize 26 | config.oauth2.resourceURI= http://localhost:8080/authenticateService/oauth/authorize 27 | -------------------------------------------------------------------------------- /oauthswager: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------