From 1bebb005afdffa5fcdd54b217a3f8bff39a39c1c Mon Sep 17 00:00:00 2001 From: "Mantena, Ravi (rx908f)" Date: Thu, 3 Sep 2020 17:14:41 -0400 Subject: New Auth Service in Mod2 Issue-ID: DCAEGEN2-2317 Change-Id: I34b08d7731cc23028f469376ef2147bb28a28b7f Signed-off-by: Ravi Mantena --- .../platform/mod/AuthServiceApplication.java | 40 +++++ .../org/onap/dcaegen2/platform/mod/DataLoader.java | 97 ++++++++++++ .../platform/mod/controllers/AuthController.java | 171 +++++++++++++++++++++ .../platform/mod/controllers/RoleController.java | 58 +++++++ .../platform/mod/controllers/UserController.java | 96 ++++++++++++ .../mod/exceptions/AppExceptionHandler.java | 52 +++++++ .../exceptions/IllegalUserOperationException.java | 34 ++++ .../mod/exceptions/RoleNotExistsException.java | 34 ++++ .../mod/exceptions/UserAlreadyExistsException.java | 34 ++++ .../mod/exceptions/UserNotFoundException.java | 34 ++++ .../platform/mod/models/GenericResponse.java | 40 +++++ .../dcaegen2/platform/mod/models/JwtResponse.java | 50 ++++++ .../dcaegen2/platform/mod/models/LoginRequest.java | 43 ++++++ .../onap/dcaegen2/platform/mod/models/ModUser.java | 75 +++++++++ .../onap/dcaegen2/platform/mod/models/Role.java | 50 ++++++ .../platform/mod/models/SignupRequest.java | 53 +++++++ .../platform/mod/models/UpdateUserRequest.java | 47 ++++++ .../platform/mod/repositories/RoleRepository.java | 37 +++++ .../platform/mod/repositories/UserRepository.java | 40 +++++ .../mod/security/WebSecurityConfigurer.java | 92 +++++++++++ .../mod/security/jwt/AuthEntryPointJwt.java | 51 ++++++ .../platform/mod/security/jwt/AuthTokenFilter.java | 81 ++++++++++ .../platform/mod/security/jwt/JwtUtils.java | 90 +++++++++++ .../mod/security/services/UserDetailsImpl.java | 127 +++++++++++++++ .../security/services/UserDetailsServiceImpl.java | 100 ++++++++++++ .../mod/services/MODUserDetailService.java | 56 +++++++ .../src/main/resources/application.properties | 32 ++++ 27 files changed, 1714 insertions(+) create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java create mode 100644 mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java create mode 100644 mod2/auth-service/src/main/resources/application.properties (limited to 'mod2/auth-service/src/main') diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java new file mode 100644 index 0000000..5b147bf --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java @@ -0,0 +1,40 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author + * @date 09/08/2020 + * Auth Service Application + */ +@SpringBootApplication +public class AuthServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(AuthServiceApplication.class, args); + } + +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java new file mode 100644 index 0000000..959b450 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java @@ -0,0 +1,97 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod; + +import org.onap.dcaegen2.platform.mod.models.ModUser; +import org.onap.dcaegen2.platform.mod.models.Role; +import org.onap.dcaegen2.platform.mod.repositories.RoleRepository; +import org.onap.dcaegen2.platform.mod.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +/** + * @author + * @date 09/08/2020 + * To Initialize Roles and create Default Admin User + */ +@Component +public class DataLoader implements ApplicationRunner { + + @Autowired + private RoleRepository roleRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + PasswordEncoder passwordEncoder; + + @Override + public void run(ApplicationArguments args) throws Exception { + populateRoles(); + populateAdminUser(); + } + + private void populateRoles() { + List roles = createRoles(); + roles.forEach((role) -> { + boolean roleNotPresent = !roleRepository.findByName(role.getName()).isPresent(); + if(roleNotPresent) + roleRepository.save(role); + }); + + } + + private List createRoles() { + Role admin = new Role("ROLE_ADMIN"); + Role user = new Role("ROLE_USER"); + Role developer = new Role("ROLE_DEVELOPER"); + return Arrays.asList(admin, user, developer); + } + + private void populateAdminUser() { + boolean adminNotPresent = !userRepository.findByUsername("admin").isPresent(); + if(adminNotPresent) { + ModUser admin = createAdmin(); + userRepository.save(admin); + } + } + + private ModUser createAdmin() { + ModUser admin = new ModUser(); + admin.setUsername("admin"); + admin.setFullName("Admin"); + admin.setPassword(passwordEncoder.encode("admin@mod")); + HashSet roleAdmin = new HashSet<>(); + roleAdmin.add(roleRepository.findByName("ROLE_ADMIN").get()); + admin.setRoles(roleAdmin); + return admin; + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java new file mode 100644 index 0000000..6612138 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java @@ -0,0 +1,171 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.controllers; + +import org.onap.dcaegen2.platform.mod.exceptions.RoleNotExistsException; +import org.onap.dcaegen2.platform.mod.exceptions.UserAlreadyExistsException; +import org.onap.dcaegen2.platform.mod.models.LoginRequest; +import org.onap.dcaegen2.platform.mod.models.JwtResponse; +import org.onap.dcaegen2.platform.mod.models.SignupRequest; +import org.onap.dcaegen2.platform.mod.models.ModUser; +import org.onap.dcaegen2.platform.mod.models.GenericResponse; +import org.onap.dcaegen2.platform.mod.models.Role; +import org.onap.dcaegen2.platform.mod.repositories.RoleRepository; +import org.onap.dcaegen2.platform.mod.repositories.UserRepository; +import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils; +import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + + +import javax.validation.Valid; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + + +/** + * @author + * @date 09/08/2020 + * Authentication Operations + */ +@RestController +@RequestMapping("/api/auth") +@CrossOrigin(origins = "*") +public class AuthController { + + @Autowired + AuthenticationManager authenticationManager; + + @Autowired + UserRepository userRepository; + + @Autowired + RoleRepository roleRepository; + + @Autowired + PasswordEncoder passwordEncoder; + + @Autowired + JwtUtils jwtUtils; + + @PreAuthorize("isAuthenticated()") + @PostMapping("/validate-token") + public ResponseEntity validateToken() { + return new ResponseEntity("true", HttpStatus.OK); + } + + @PostMapping("/signin") + public ResponseEntity authenticateUser(@RequestBody @Valid LoginRequest loginRequest) { + Authentication authentication = authenticateLoginRequest(loginRequest); + SecurityContextHolder.getContext().setAuthentication(authentication); + String jwt = jwtUtils.generateJwtToken(authentication); + return setUserContext(authentication, jwt); + } + + private Authentication authenticateLoginRequest(@RequestBody @Valid LoginRequest loginRequest) { + return authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()) + ); + } + + private ResponseEntity setUserContext(Authentication authentication, String jwt) { + UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal(); + List roles = setRolesFromUserDetails(userDetails); + return buildUserContext(jwt, userDetails, roles); + } + + private List setRolesFromUserDetails(UserDetailsImpl userDetails) { + return userDetails.getAuthorities().stream() + .map(item -> ((GrantedAuthority) item).getAuthority()) + .collect(Collectors.toList()); + } + + private ResponseEntity buildUserContext(String jwt, UserDetailsImpl userDetails, List roles) { + return ResponseEntity.ok(JwtResponse.builder() + .id(userDetails.getId()) + .roles(roles) + .username(userDetails.getUsername()) + .token(jwt) + .fullName(userDetails.getFullName()) + .build() + ); + } + + @PreAuthorize("hasRole('ADMIN')") + @PostMapping("/signup") + public ResponseEntity registerUser(@RequestBody @Valid SignupRequest request) { + checkIfUserExists(request); + ModUser user = createNewUser(request); + userRepository.save(user); + return ResponseEntity.ok(new GenericResponse("User registered successfully!")); + } + + private void checkIfUserExists(@RequestBody @Valid SignupRequest signUpRequest) { + if (userRepository.existsByUsername(signUpRequest.getUsername())) + throw new UserAlreadyExistsException("Username already exists!"); + } + + private ModUser createNewUser(@RequestBody @Valid SignupRequest request) { + ModUser user = new ModUser(); + user.setUsername(request.getUsername()); + user.setFullName(request.getFullName()); + user.setPassword(getEncodedPassword(request)); + Set roles = createRoles(request.getRoles()); + user.setRoles(roles); + return user; + } + + private String getEncodedPassword(@RequestBody @Valid SignupRequest request) { + return passwordEncoder.encode(request.getPassword()); + } + + public Set createRoles(Set roleStrings) { + Set roles = new HashSet<>(); + for (String roleStr : roleStrings) { + roles.add(getRole(roleStr)); + } + return roles; + } + + private Role getRole(String roleStr) { + return roleRepository.findByName(roleStr).orElseThrow( + () -> new RoleNotExistsException(String.format("Role %s does not exist", roleStr))); + } +} + + diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java new file mode 100644 index 0000000..e129cda --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java @@ -0,0 +1,58 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.controllers; + +import org.onap.dcaegen2.platform.mod.repositories.RoleRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author + * @date 09/08/2020 + * Role Operations + */ +@RestController +@RequestMapping("/api/roles") +@CrossOrigin(origins = "*") +public class RoleController { + + @Autowired + RoleRepository roleRepository; + + @GetMapping + @ResponseStatus(HttpStatus.OK) + public List getRoles(){ + return roleRepository.findAll() + .stream() + .map(role -> role.getName()) + .collect(Collectors.toList()); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java new file mode 100644 index 0000000..90e7b62 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java @@ -0,0 +1,96 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.controllers; + +import org.onap.dcaegen2.platform.mod.exceptions.UserNotFoundException; +import org.onap.dcaegen2.platform.mod.models.GenericResponse; +import org.onap.dcaegen2.platform.mod.models.ModUser; +import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest; +import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl; +import org.onap.dcaegen2.platform.mod.services.MODUserDetailService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + + +/** + * @author + * @date 09/08/2020 + * User Operations + */ +@RestController +@RequestMapping("/api/users") +@CrossOrigin(origins = "*") +public class UserController { + + @Autowired + private MODUserDetailService modUserDetailService; + + @Autowired + private UserDetailsServiceImpl userDetailsService; + + @PreAuthorize("hasRole('ADMIN')") + @GetMapping("/getAll") + @ResponseStatus(HttpStatus.OK) + public List getAllUsers() { + return modUserDetailService.findAll(); + } + + @PreAuthorize("hasRole('ADMIN') or hasRole('USER')") + @GetMapping("/{username}") + public UserDetails getUser(@PathVariable String username) { + return userDetailsService.loadUserByUsername(username); + } + + @PreAuthorize("hasRole('ADMIN')") + @PatchMapping("/admin/{username}") + public ModUser adminUpdateUserProfile(@PathVariable String username, @RequestBody @Valid UpdateUserRequest + userRequest, @RequestHeader (name="Authorization") String token) { + return userDetailsService.adminUpdateUser(username, userRequest, token); + } + + @PreAuthorize("hasRole('USER') or hasRole('DEVELOPER')") + @PatchMapping("/user/{username}") + public ModUser userUpdateOwnProfile(@PathVariable String username, @RequestBody @Valid UpdateUserRequest + userRequest, @RequestHeader (name="Authorization") String token) { + return userDetailsService.userUpdateOwnProfile(username, userRequest, token); + } + + @PreAuthorize("hasRole('ADMIN')") + @DeleteMapping("/{username}") + public ResponseEntity deleteUser(@PathVariable String username) { + modUserDetailService.deleteUserByUsername(username); + return ResponseEntity.ok(new GenericResponse("User " + username + " was removed")); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.NOT_FOUND) + public void userNotFoundHandler(UserNotFoundException ex) { + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java new file mode 100644 index 0000000..e029e69 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java @@ -0,0 +1,52 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.exceptions; + +import org.onap.dcaegen2.platform.mod.models.GenericResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +/** + * @author + * @date 09/08/2020 + * Exception handler for the Auth Service Application + */ +@ControllerAdvice +@Slf4j +public class AppExceptionHandler { + + @ExceptionHandler + public ResponseEntity resolveRuntimeException(UserAlreadyExistsException ex){ + log.error(ex.getMessage()); + return new ResponseEntity<>(new GenericResponse(ex.getMessage()), HttpStatus.CONFLICT); + } + + @ExceptionHandler + public ResponseEntity resolveRoleNotFoundException(RoleNotExistsException ex){ + log.error(ex.getMessage()); + return new ResponseEntity<>(new GenericResponse(ex.getMessage()), HttpStatus.BAD_REQUEST); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java new file mode 100644 index 0000000..4a5837a --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java @@ -0,0 +1,34 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.exceptions; + +/** + * @author + * @date 09/08/2020 + * Exception for Illegal Operation + */ +public class IllegalUserOperationException extends RuntimeException { + public IllegalUserOperationException(String s) { + super(s); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java new file mode 100644 index 0000000..dfa6efb --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java @@ -0,0 +1,34 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.exceptions; + +/** + * @author + * @date 09/08/2020 + * Exception for Role not exist + */ +public class RoleNotExistsException extends RuntimeException { + public RoleNotExistsException(String message) { + super(message); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java new file mode 100644 index 0000000..475dc44 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java @@ -0,0 +1,34 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.exceptions; + +/** + * @author + * @date 09/08/2020 + * Exception for User already exists + */ +public class UserAlreadyExistsException extends RuntimeException { + public UserAlreadyExistsException(String message) { + super(message); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java new file mode 100644 index 0000000..95c6a70 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java @@ -0,0 +1,34 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.exceptions; + +/** + * @author + * @date 09/08/2020 + * Exception for User Not Found + */ +public class UserNotFoundException extends RuntimeException { + public UserNotFoundException(String s) { + super(s); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java new file mode 100644 index 0000000..c4625a4 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java @@ -0,0 +1,40 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.models; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * @author + * @date 09/08/2020 + * Generic Response for the Auth Service Request + */ +@Getter +@Setter +@AllArgsConstructor +public class GenericResponse { + + private String message; +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java new file mode 100644 index 0000000..8855245 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java @@ -0,0 +1,50 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.models; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author + * @date 09/08/2020 + * JWT Response for the Auth Service Request + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class JwtResponse { + + private String token; + private String type = "Bearer"; + private String id; + private String username; + private String fullName; + private List roles; + +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java new file mode 100644 index 0000000..af0f710 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java @@ -0,0 +1,43 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.models; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author + * @date 09/08/2020 + * Login request + */ +@Data +public class LoginRequest { + + @NotBlank + private String username; + + @NotBlank + private String password; + +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java new file mode 100644 index 0000000..4da5c98 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java @@ -0,0 +1,75 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.models; + +import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.DBRef; +import org.springframework.data.mongodb.core.mapping.Document; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +/** + * @author + * @date 09/08/2020 + * Assigning Roles to User + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@Document(collection = "users") +public class ModUser implements Serializable { + + @Id + public String _id; + + @NotBlank + @Size(max = 10) + private String username; + + @NotBlank + private String password; + + @NotBlank + private String fullName; + + @DBRef + private Set roles = new HashSet<>(); + + public ModUser(@NotBlank @Size(max = 10) String username, @NotBlank String password, @NotBlank String fullName) { + this.username = username; + this.password = password; + this.fullName=fullName; + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java new file mode 100644 index 0000000..8cce344 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java @@ -0,0 +1,50 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.models; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +/** + * @author + * @date 09/08/2020 + * Roles + */ +@Document(collection = "roles") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Role { + + @Id + private String id; + + private String name; + + public Role(String name) { + this.name = name; + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java new file mode 100644 index 0000000..f705d76 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java @@ -0,0 +1,53 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.models; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.Set; + +/** + * @author + * @date 09/08/2020 + * To validate User enter Details + */ +@Data +public class SignupRequest { + + @NotBlank(message = "username must not be blank") + @Size(min = 5, max = 10, message = "username must be between 5 and 10 characters.") + private String username; + + @NotNull(message = "username must not be null") + @Size(min = 1, message = "At least 1 role must be passed") + private Set roles; + + @NotBlank(message = "password must not be blank") + private String password; + + @NotBlank(message = "Full name must not be blank") + private String fullName; +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java new file mode 100644 index 0000000..6e3abf6 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java @@ -0,0 +1,47 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.models; + +import lombok.Data; + +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import java.util.Set; + +/** + * @author + * @date 09/08/2020 + * To update User Details of Name and Password + */ +@Data +public class UpdateUserRequest { + + @Size(min = 1, message = "At least 1 role must be passed") + private Set roles; + + @Pattern(regexp = "^(?!\\s*$).+", message = "password must not be blank") + private String password; + + @Pattern(regexp = "^(?!\\s*$).+", message = "fullName must not be blank") + private String fullName; +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java new file mode 100644 index 0000000..6efad17 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java @@ -0,0 +1,37 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.repositories; + +import org.onap.dcaegen2.platform.mod.models.Role; +import org.springframework.data.mongodb.repository.MongoRepository; + +import java.util.Optional; + +/** + * @author + * @date 09/08/2020 + * Interface to find user exists or not + */ +public interface RoleRepository extends MongoRepository { + Optional findByName(String name); +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java new file mode 100644 index 0000000..442ebf1 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java @@ -0,0 +1,40 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.repositories; + +import org.onap.dcaegen2.platform.mod.models.ModUser; +import org.springframework.data.mongodb.repository.MongoRepository; + +import java.util.Optional; + +/** + * @author + * @date 09/08/2020 + * Interface to Find/Valid/Delete user + */ +public interface UserRepository extends MongoRepository{ + Optional findByUsername(String username); + Boolean existsByUsername(String username); + void deleteByUsername(String username); +} + diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java new file mode 100644 index 0000000..cfccce4 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java @@ -0,0 +1,92 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.security; + +import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt; +import org.onap.dcaegen2.platform.mod.security.jwt.AuthTokenFilter; +import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + + +/** + * @author + * @date 09/08/2020 + * Allows customization to the Spring WebSecurity + */ + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter { + + @Autowired + UserDetailsServiceImpl userDetailsService; + + @Autowired + private AuthEntryPointJwt unauthorizedHandler; + + @Bean + public AuthTokenFilter authenticationJwtTokenFilter(){ + return new AuthTokenFilter(); + } + + @Override + protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { + authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception{ + return super.authenticationManagerBean(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.cors().and().csrf().disable() + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .authorizeRequests().antMatchers("/api/auth/**").permitAll() + .antMatchers("/api/users/**").permitAll() + .anyRequest().authenticated(); + + http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java new file mode 100644 index 0000000..310d487 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java @@ -0,0 +1,51 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.security.jwt; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author + * @date 09/08/2020 + * JWT Authentication Entry Point + */ + +@Slf4j +@Component +public class AuthEntryPointJwt implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException authException) throws IOException, ServletException { + log.error("Unauthorized error: {}", authException.getMessage()); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized"); + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java new file mode 100644 index 0000000..012c333 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java @@ -0,0 +1,81 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.security.jwt; + +import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author + * @date 09/08/2020 + * Authentication Token Filter + */ +@Slf4j +public class AuthTokenFilter extends OncePerRequestFilter { + + @Autowired + private JwtUtils jwtUtils; + + @Autowired + private UserDetailsServiceImpl userDetailsService; + + @Override + protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + try{ + String jwt = parseJwt(httpServletRequest); + if (jwt != null && jwtUtils.validateJwtToken(jwt)){ + String username = jwtUtils.getUserNameFromJwtToken(jwt); + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest)); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + }catch (Exception e){ + logger.error("Cannot set user authentication: {}", e); + } + filterChain.doFilter(httpServletRequest, httpServletResponse); + } + + private String parseJwt(HttpServletRequest httpServletRequest) { + String headerAuth = httpServletRequest.getHeader("Authorization"); + + if(StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")){ + return headerAuth.substring(7, headerAuth.length()); + } + return null; + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java new file mode 100644 index 0000000..3b6d311 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java @@ -0,0 +1,90 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.security.jwt; + +import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.SignatureException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * @author + * @date 09/08/2020 + * JWT Utils + */ +@Slf4j +@Component +public class JwtUtils { + + @Value("${mod-portal.jwt.secret}") + private String jwtSecret; + + @Value("${mod-portal.jwt.jwtExpirationMs}") + private int jwtExpirationMs; + + public String generateJwtToken(Authentication authentication) { + + UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); + + return Jwts.builder() + .setSubject((userPrincipal.getUsername())) + .claim("roles", userPrincipal.getAuthoritiesAsList()) + .claim("fullName", userPrincipal.getFullName()) + .setIssuedAt(new Date()) + .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs)) + .signWith(SignatureAlgorithm.HS512, jwtSecret) + .compact(); + } + + public String getUserNameFromJwtToken(String token) { + return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject(); + } + + public boolean validateJwtToken(String authToken) { + try { + Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken); + return true; + } catch (SignatureException e) { + log.error("Invalid JWT signature: {}", e.getMessage()); + } catch (MalformedJwtException e) { + log.error("Invalid JWT token: {}", e.getMessage()); + } catch (ExpiredJwtException e) { + log.error("JWT token is expired: {}", e.getMessage()); + } catch (UnsupportedJwtException e) { + log.error("JWT token is unsupported: {}", e.getMessage()); + } catch (IllegalArgumentException e) { + log.error("JWT claims string is empty: {}", e.getMessage()); + } + + return false; + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java new file mode 100644 index 0000000..82cb577 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java @@ -0,0 +1,127 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.security.services; + +import org.onap.dcaegen2.platform.mod.models.ModUser; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.EqualsAndHashCode; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author + * @date 09/08/2020 + * User Details Implementation + */ +@EqualsAndHashCode +public class UserDetailsImpl implements UserDetails{ + + private static final long serialVersionUID = 1L; + + private String id; + + private String username; + + private String fullName; + + @JsonIgnore + private String password; + + private Collection authorities; + + public UserDetailsImpl(String id, String username, String fullName, String password, Collection authorities) { + this.id = id; + this.username = username; + this.fullName = fullName; + this.password = password; + this.authorities = authorities; + } + + public static UserDetails build(ModUser user) { + List authorities = user.getRoles().stream() + .map(role -> new SimpleGrantedAuthority(role.getName())) + .collect(Collectors.toList()); + + return new UserDetailsImpl( + user.get_id(), + user.getUsername(), + user.getFullName(), + user.getPassword(), + authorities + ); + } + + public String getId() { + return id; + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + public List getAuthoritiesAsList(){ + return authorities.stream().map(GrantedAuthority::getAuthority) + .collect(Collectors.toList()); + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return username; + } + + public String getFullName() { + return fullName; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java new file mode 100644 index 0000000..5c13e11 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java @@ -0,0 +1,100 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.security.services; + +import org.onap.dcaegen2.platform.mod.controllers.AuthController; +import org.onap.dcaegen2.platform.mod.exceptions.UserNotFoundException; +import org.onap.dcaegen2.platform.mod.exceptions.IllegalUserOperationException; +import org.onap.dcaegen2.platform.mod.models.ModUser; +import org.onap.dcaegen2.platform.mod.models.Role; +import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest; +import org.onap.dcaegen2.platform.mod.repositories.UserRepository; +import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.Set; + +/** + * @author + * @date 09/08/2020 + * User Details Service + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + + @Autowired + @Setter + UserRepository userRepository; + + @Autowired + PasswordEncoder passwordEncoder; + + @Autowired + AuthController authController; + + @Autowired + private JwtUtils jwtUtils; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + ModUser user = userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username)); + + return UserDetailsImpl.build(user); + } + + public ModUser adminUpdateUser(String username, UpdateUserRequest userRequest, String token) { + return updateUserProfile(username, userRequest); + } + + public ModUser userUpdateOwnProfile(String username, UpdateUserRequest userRequest, String token) { + String usernameFromToken = jwtUtils.getUserNameFromJwtToken(token.substring(7)); + if (usernameFromToken.equals(username)) { + return updateUserProfile(username, userRequest); + } else { + throw new IllegalUserOperationException("Permission denied to update user profile of " + username); + } + } + + private ModUser updateUserProfile(String username, UpdateUserRequest userRequest) { + ModUser modUser = userRepository.findByUsername(username).orElseThrow(() -> new UserNotFoundException(String.format("User %s not found", username))); + modUser = updateUserFields(modUser, userRequest); + return userRepository.save(modUser); + } + + private ModUser updateUserFields(ModUser modUser, UpdateUserRequest userRequest) { + if (userRequest.getFullName() != null) modUser.setFullName(userRequest.getFullName()); + if (userRequest.getPassword() != null) modUser.setPassword(passwordEncoder.encode(userRequest.getPassword())); + if (userRequest.getRoles() != null) { + Set roles = authController.createRoles(userRequest.getRoles()); + modUser.setRoles(roles); + } + return modUser; + } +} diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java new file mode 100644 index 0000000..a6a6de5 --- /dev/null +++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java @@ -0,0 +1,56 @@ +/* + * + * * ============LICENSE_START======================================================= + * * org.onap.dcae + * * ================================================================================ + * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * * ================================================================================ + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END========================================================= + * + */ + +package org.onap.dcaegen2.platform.mod.services; + +import org.onap.dcaegen2.platform.mod.models.ModUser; +import org.onap.dcaegen2.platform.mod.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author + * @date 09/08/2020 + * This Service provides APIs to manage User Entity + */ + +@Service +public class MODUserDetailService { + + @Autowired + private UserRepository userRepository; + + public MODUserDetailService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public List findAll() { + return userRepository.findAll(); + } + + public void deleteUserByUsername(String username) { + userRepository.deleteByUsername(username); + } + +} diff --git a/mod2/auth-service/src/main/resources/application.properties b/mod2/auth-service/src/main/resources/application.properties new file mode 100644 index 0000000..f3f5d37 --- /dev/null +++ b/mod2/auth-service/src/main/resources/application.properties @@ -0,0 +1,32 @@ +# +# /* +# * ============LICENSE_START======================================================= +# * org.onap.dcae +# * ================================================================================ +# * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. +# * ================================================================================ +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * ============LICENSE_END========================================================= +# */ +# + +server.port=8082 + +#spring.data.mongodb.host=mongo_db +spring.data.mongodb.host=localhost +#spring.data.mongodb.host=zlecdyh2bdcc1s2dokr05.ec53e7.dyh2b.tci.att.com +spring.data.mongodb.port=27017 +spring.data.mongodb.database=dcae_mod + +mod-portal.jwt.secret=mod2020! +mod-portal.jwt.jwtExpirationMs=43200000 \ No newline at end of file -- cgit 1.2.3-korg