RequestHeaderAuthenticationProvider.java
package se.jobtechdev.personaldatagateway.api.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;
import se.jobtechdev.personaldatagateway.api.generated.entities.ClientEntity;
import se.jobtechdev.personaldatagateway.api.service.ClientService;
import se.jobtechdev.personaldatagateway.api.util.AuthUtil;
import se.jobtechdev.personaldatagateway.api.util.TimeProvider;
import java.util.List;
@Component
public class RequestHeaderAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger =
LoggerFactory.getLogger(RequestHeaderAuthenticationProvider.class);
private final ClientService clientService;
@Autowired
public RequestHeaderAuthenticationProvider(ClientService clientService) {
this.clientService = clientService;
}
public ClientEntity getClientByKey(String authKey) {
AuthUtil.assertAuthKeyExists(authKey);
final byte[] decodedAuthKey = AuthUtil.decodeAuthKey(authKey);
final byte[] authKeyHash = AuthUtil.hashDecodedAuthKey(decodedAuthKey);
final var optionalClient = clientService.getClientByKeyHash(authKeyHash);
if (optionalClient.isEmpty())
throw new BadCredentialsException(
"Bad Request Header Credentials, provided authKey does not match any known client");
return optionalClient.get();
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
final var principal = authentication.getPrincipal();
if (principal == null) {
throw new BadCredentialsException(
"Bad Request Header Credentials, provided principal is null");
}
final var authKey = String.valueOf(authentication.getPrincipal());
final var client = getClientByKey(authKey);
logger.debug(
"Received authenticated http request by {}[id={}, role={}, revoked={}]",
client.getName(),
client.getId(),
client.getRole(),
client.getRevoked());
if (client.getRevoked() != null && TimeProvider.now().isAfter(client.getRevoked())) {
throw new BadCredentialsException(
"Bad Request Header Credentials, provided client is revoked");
}
final var role = client.getRole();
final var simpleGrantedAuthority = new SimpleGrantedAuthority(role);
MDC.put("temp.custom.pdg-api.clientid", client.getId().toString());
MDC.put("temp.log", "true");
return new PreAuthenticatedAuthenticationToken(
client.getId().toString(), null, List.of(simpleGrantedAuthority));
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(PreAuthenticatedAuthenticationToken.class);
}
}