Skip to content
Snippets Groups Projects
Verified Commit d187b62e authored by Martin Weise's avatar Martin Weise
Browse files

Finally able to create users

parent c121f298
Branches
Tags
2 merge requests!163Relase 1.3.0,!155Added readme to authentication service and added eureka service
Showing
with 121 additions and 18 deletions
...@@ -16,11 +16,13 @@ import javax.validation.constraints.NotNull; ...@@ -16,11 +16,13 @@ import javax.validation.constraints.NotNull;
public class TokenDto { public class TokenDto {
@NotBlank @NotBlank
@ToString.Exclude
@JsonProperty("access_token") @JsonProperty("access_token")
@Schema(example = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJBbFdvalRsa1dBSVVoYTJLWjFvOEluWEtNbVAzUTg0STZiMFFHYkR6aEpvIn0.eyJleHAiOjE2ODAyNjgyNjgsImlhdCI6MTY4MDI2ODIwOCwianRpIjoiNjkwNjRlNTQtODNhNS00NGYxLWE3OTItNWFjOWU4OTA5YTlkIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJzdWIiOiI4MjQ2OWMyMS0yYjNjLTRmMDctODg1Yi1hMzViMGQ5YTJhNjYiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIiwiYWNyIjoiMSIsInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjQ0NTgwN2VlLTI4NzYtNDYxZC1hOGYzLTRkMjdiMzBjMjFmYSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoiZmRhIn0.IOQxqWvlPDV9WuFOeLVG-ayexbK8OqylPABghEMSbMpmNlQhSAjbjaMY31uU-uADZRHB-mC8bmRS5PoWNtanuhz0lORDCeissFsbv0UL9Q42CaxG75vFAAD5WsdIHIr-dtEjEiXYtu-qwdg83griAUeO119TTdgldyPxo4jWzNw0ui6W7r4LqP4fSk31iJfxR5urgs5k6Ctzg-fXCORT31-nKz_YJQwLoPO9j4afX_1mnCXY5qFGMSrmPKzB0CArZfUpa_4nqt4Y768yOC3gigAyCjXtvXKkgCmARPSRjERGDdTb6SGbAwRDiVHVy9wy7XZwOcCFMEra9H7mV0Mx2A") @Schema(example = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJBbFdvalRsa1dBSVVoYTJLWjFvOEluWEtNbVAzUTg0STZiMFFHYkR6aEpvIn0.eyJleHAiOjE2ODAyNjgyNjgsImlhdCI6MTY4MDI2ODIwOCwianRpIjoiNjkwNjRlNTQtODNhNS00NGYxLWE3OTItNWFjOWU4OTA5YTlkIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJzdWIiOiI4MjQ2OWMyMS0yYjNjLTRmMDctODg1Yi1hMzViMGQ5YTJhNjYiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIiwiYWNyIjoiMSIsInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjQ0NTgwN2VlLTI4NzYtNDYxZC1hOGYzLTRkMjdiMzBjMjFmYSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoiZmRhIn0.IOQxqWvlPDV9WuFOeLVG-ayexbK8OqylPABghEMSbMpmNlQhSAjbjaMY31uU-uADZRHB-mC8bmRS5PoWNtanuhz0lORDCeissFsbv0UL9Q42CaxG75vFAAD5WsdIHIr-dtEjEiXYtu-qwdg83griAUeO119TTdgldyPxo4jWzNw0ui6W7r4LqP4fSk31iJfxR5urgs5k6Ctzg-fXCORT31-nKz_YJQwLoPO9j4afX_1mnCXY5qFGMSrmPKzB0CArZfUpa_4nqt4Y768yOC3gigAyCjXtvXKkgCmARPSRjERGDdTb6SGbAwRDiVHVy9wy7XZwOcCFMEra9H7mV0Mx2A")
private String accessToken; private String accessToken;
@NotBlank @NotBlank
@ToString.Exclude
@JsonProperty("refresh_token") @JsonProperty("refresh_token")
@Schema(example = "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4YTczZGYwZS03NzMwLTRiZDEtOGVhOC1mZTdjZWViNmMxYWMifQ.eyJleHAiOjE2ODAyNzAwMDgsImlhdCI6MTY4MDI2ODIwOCwianRpIjoiNWYyNDIwNDItNmJmZi00ZTQ2LTg2NTAtNDBhY2E3YjVkZjMyIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL21hc3RlciIsInN1YiI6IjgyNDY5YzIxLTJiM2MtNGYwNy04ODViLWEzNWIwZDlhMmE2NiIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIiwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwic2lkIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIn0.-GltWGkIaKUJ4AqRYnGHblTr0ygZm2CsRQB6zz5ePm4") @Schema(example = "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4YTczZGYwZS03NzMwLTRiZDEtOGVhOC1mZTdjZWViNmMxYWMifQ.eyJleHAiOjE2ODAyNzAwMDgsImlhdCI6MTY4MDI2ODIwOCwianRpIjoiNWYyNDIwNDItNmJmZi00ZTQ2LTg2NTAtNDBhY2E3YjVkZjMyIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL21hc3RlciIsInN1YiI6IjgyNDY5YzIxLTJiM2MtNGYwNy04ODViLWEzNWIwZDlhMmE2NiIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIiwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwic2lkIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIn0.-GltWGkIaKUJ4AqRYnGHblTr0ygZm2CsRQB6zz5ePm4")
private String refreshToken; private String refreshToken;
......
...@@ -10,6 +10,7 @@ import io.micrometer.core.annotation.Timed; ...@@ -10,6 +10,7 @@ import io.micrometer.core.annotation.Timed;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -57,7 +58,8 @@ public class UserEndpoint { ...@@ -57,7 +58,8 @@ public class UserEndpoint {
log.debug("endpoint create a user, data={}", data); log.debug("endpoint create a user, data={}", data);
final UserBriefDto dto = userMapper.userToUserBriefDto(userService.create(data)); final UserBriefDto dto = userMapper.userToUserBriefDto(userService.create(data));
log.trace("create user resulted in dto {}", dto); log.trace("create user resulted in dto {}", dto);
return ResponseEntity.ok(dto); return ResponseEntity.status(HttpStatus.CREATED)
.body(dto);
} }
} }
...@@ -31,7 +31,7 @@ server: ...@@ -31,7 +31,7 @@ server:
port: 9098 port: 9098
ssl: ssl:
enabled: true enabled: true
key-alias: server key-alias: user-service
key-store: "./server.keystore" key-store: "./server.keystore"
key-store-type: jks key-store-type: jks
key-store-password: password key-store-password: password
...@@ -51,7 +51,7 @@ eureka: ...@@ -51,7 +51,7 @@ eureka:
client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/
fda: fda:
ready.path: ./ready ready.path: ./ready
gateway.endpoint: https://localhost:9095 gateway.endpoint: https://gateway-service:9095
keycloak: keycloak:
username: fda username: fda
password: fda password: fda
......
package at.tuwien.auth;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AdminToken {
private static AdminToken instance = null;
private String token;
public static synchronized AdminToken getInstance() {
if (instance == null) {
instance = new AdminToken();
}
return instance;
}
}
package at.tuwien.config; package at.tuwien.config;
import at.tuwien.mapper.AuthenticationMapper;
import lombok.Getter; import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -20,10 +22,18 @@ public class GatewayConfig { ...@@ -20,10 +22,18 @@ public class GatewayConfig {
@Value("${fda.keycloak.password}") @Value("${fda.keycloak.password}")
private String keycloakPassword; private String keycloakPassword;
private final AuthenticationMapper authenticationMapper;
@Autowired
public GatewayConfig(AuthenticationMapper authenticationMapper) {
this.authenticationMapper = authenticationMapper;
}
@Bean @Bean
public RestTemplate restTemplate() { public RestTemplate restTemplate() {
final RestTemplate restTemplate = new RestTemplate(); final RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint)); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint));
restTemplate.getMessageConverters().add(authenticationMapper.mappingJackson2HttpMessageConverter());
return restTemplate; return restTemplate;
} }
} }
...@@ -32,17 +32,19 @@ public class GatewayServiceGatewayImpl implements GatewayServiceGateway { ...@@ -32,17 +32,19 @@ public class GatewayServiceGatewayImpl implements GatewayServiceGateway {
@Override @Override
public TokenDto getToken() throws RemoteUnavailableException { public TokenDto getToken() throws RemoteUnavailableException {
final HttpHeaders headers = new HttpHeaders(); final HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED.toString()); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>(); final MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
payload.add("username", gatewayConfig.getKeycloakUsername()); data.set("username", gatewayConfig.getKeycloakUsername());
payload.add("password", gatewayConfig.getKeycloakPassword()); data.set("password", gatewayConfig.getKeycloakPassword());
payload.add("grant_type", "password"); data.set("grant_type", "password");
payload.add("client_id", "admin-cli"); data.set("client_id", "admin-cli");
final String url = "/api/auth/realms/master/protocol/openid-connect/token"; final String url = "/api/auth/realms/master/protocol/openid-connect/token";
log.debug("call authentication service {}", url); log.debug("call authentication service {}", url);
log.trace("headers: {}", headers);
log.trace("data: {}", data);
final ResponseEntity<TokenDto> response; final ResponseEntity<TokenDto> response;
try { try {
response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data, headers), TokenDto.class);
} catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
log.error("Failed to obtain admin token: {}", e.getMessage()); log.error("Failed to obtain admin token: {}", e.getMessage());
throw new RemoteUnavailableException("Failed to obtain admin token", e); throw new RemoteUnavailableException("Failed to obtain admin token", e);
...@@ -57,9 +59,10 @@ public class GatewayServiceGatewayImpl implements GatewayServiceGateway { ...@@ -57,9 +59,10 @@ public class GatewayServiceGatewayImpl implements GatewayServiceGateway {
@Override @Override
public void createUser(String token, CreateUserDto data) throws RemoteUnavailableException { public void createUser(String token, CreateUserDto data) throws RemoteUnavailableException {
final HttpHeaders headers = new HttpHeaders(); final HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", MediaType.APPLICATION_JSON.toString()); headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", MediaType.APPLICATION_JSON.toString()); headers.setBearerAuth(token);
headers.add("Authorization", "Bearer: " + token); log.trace("headers: {}", headers);
log.trace("data: {}", data);
final ResponseEntity<Void> response; final ResponseEntity<Void> response;
try { try {
response = restTemplate.exchange("/api/auth/admin/realms/dbrepo/users", HttpMethod.POST, new HttpEntity<>(data, headers), Void.class); response = restTemplate.exchange("/api/auth/admin/realms/dbrepo/users", HttpMethod.POST, new HttpEntity<>(data, headers), Void.class);
......
package at.tuwien.listener;
import at.tuwien.api.auth.TokenDto;
import at.tuwien.auth.AdminToken;
import at.tuwien.exception.RemoteUnavailableException;
import at.tuwien.gateway.GatewayServiceGateway;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Log4j2
@Component
public class AdminTokenScheduler {
private final AdminToken adminToken;
private final GatewayServiceGateway gatewayServiceGateway;
@Autowired
public AdminTokenScheduler(GatewayServiceGateway gatewayServiceGateway) {
this.gatewayServiceGateway = gatewayServiceGateway;
this.adminToken = AdminToken.getInstance();
}
@Scheduled(fixedRate = 1000 * 60 * 3)
public void retrieveAdminToken() throws RemoteUnavailableException {
final TokenDto tokenDto = gatewayServiceGateway.getToken();
log.trace("retrieved new admin token: {}", tokenDto);
adminToken.setToken(tokenDto.getAccessToken());
}
}
package at.tuwien.mapper;
import org.mapstruct.Mapper;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.util.Collections;
@Mapper(componentModel = "spring")
public interface AuthenticationMapper {
org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AuthenticationMapper.class);
default MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_FORM_URLENCODED));
return mappingJackson2HttpMessageConverter;
}
}
package at.tuwien.mapper; package at.tuwien.mapper;
import at.tuwien.api.auth.CreateUserDto; import at.tuwien.api.auth.CreateUserDto;
import at.tuwien.api.auth.CredentialDto;
import at.tuwien.api.auth.SignupRequestDto; import at.tuwien.api.auth.SignupRequestDto;
import at.tuwien.api.user.GrantedAuthorityDto; import at.tuwien.api.user.GrantedAuthorityDto;
import at.tuwien.api.user.UserBriefDto; import at.tuwien.api.user.UserBriefDto;
...@@ -11,6 +12,8 @@ import org.mapstruct.Mapper; ...@@ -11,6 +12,8 @@ import org.mapstruct.Mapper;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.List;
@Mapper(componentModel = "spring") @Mapper(componentModel = "spring")
public interface UserMapper { public interface UserMapper {
...@@ -22,7 +25,18 @@ public interface UserMapper { ...@@ -22,7 +25,18 @@ public interface UserMapper {
UserBriefDto userToUserBriefDto(User data); UserBriefDto userToUserBriefDto(User data);
CreateUserDto signupRequestDtoToCreateUserDto(SignupRequestDto data); default CreateUserDto signupRequestDtoToCreateUserDto(SignupRequestDto data) {
return CreateUserDto.builder()
.username(data.getUsername())
.email(data.getEmail())
.enabled(true)
.credentials(List.of(CredentialDto.builder()
.temporary(false)
.type("password")
.value(data.getPassword())
.build()))
.build();
}
default GrantedAuthority grantedAuthorityDtoToGrantedAuthority(GrantedAuthorityDto data) { default GrantedAuthority grantedAuthorityDtoToGrantedAuthority(GrantedAuthorityDto data) {
final GrantedAuthority authority = new SimpleGrantedAuthority(data.getAuthority()); final GrantedAuthority authority = new SimpleGrantedAuthority(data.getAuthority());
......
...@@ -2,7 +2,7 @@ package at.tuwien.service.impl; ...@@ -2,7 +2,7 @@ package at.tuwien.service.impl;
import at.tuwien.api.auth.CreateUserDto; import at.tuwien.api.auth.CreateUserDto;
import at.tuwien.api.auth.SignupRequestDto; import at.tuwien.api.auth.SignupRequestDto;
import at.tuwien.api.auth.TokenDto; import at.tuwien.auth.AdminToken;
import at.tuwien.entities.user.User; import at.tuwien.entities.user.User;
import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.RemoteUnavailableException;
import at.tuwien.exception.UserNotFoundException; import at.tuwien.exception.UserNotFoundException;
...@@ -21,6 +21,7 @@ import java.util.Optional; ...@@ -21,6 +21,7 @@ import java.util.Optional;
@Service @Service
public class UserServiceImpl implements UserService { public class UserServiceImpl implements UserService {
private final AdminToken adminToken;
private final UserMapper userMapper; private final UserMapper userMapper;
private final UserRepository userRepository; private final UserRepository userRepository;
private final GatewayServiceGateway authenticationServiceGateway; private final GatewayServiceGateway authenticationServiceGateway;
...@@ -28,6 +29,7 @@ public class UserServiceImpl implements UserService { ...@@ -28,6 +29,7 @@ public class UserServiceImpl implements UserService {
@Autowired @Autowired
public UserServiceImpl(UserMapper userMapper, UserRepository userRepository, public UserServiceImpl(UserMapper userMapper, UserRepository userRepository,
GatewayServiceGateway authenticationServiceGateway) { GatewayServiceGateway authenticationServiceGateway) {
this.adminToken = AdminToken.getInstance();
this.userMapper = userMapper; this.userMapper = userMapper;
this.userRepository = userRepository; this.userRepository = userRepository;
this.authenticationServiceGateway = authenticationServiceGateway; this.authenticationServiceGateway = authenticationServiceGateway;
...@@ -50,10 +52,8 @@ public class UserServiceImpl implements UserService { ...@@ -50,10 +52,8 @@ public class UserServiceImpl implements UserService {
@Override @Override
public User create(SignupRequestDto data) throws RemoteUnavailableException, UserNotFoundException { public User create(SignupRequestDto data) throws RemoteUnavailableException, UserNotFoundException {
final TokenDto dto = authenticationServiceGateway.getToken();
log.debug("obtained authentication token");
final CreateUserDto userDto = userMapper.signupRequestDtoToCreateUserDto(data); final CreateUserDto userDto = userMapper.signupRequestDtoToCreateUserDto(data);
authenticationServiceGateway.createUser(dto.getAccessToken(), userDto); authenticationServiceGateway.createUser(adminToken.getToken(), userDto);
final Optional<User> optional = userRepository.findByUsername(data.getUsername()); final Optional<User> optional = userRepository.findByUsername(data.getUsername());
if (optional.isEmpty()) { if (optional.isEmpty()) {
/* should never occur */ /* should never occur */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment