Adding JWT MtM Authentication
Overview
Atoti Limits includes native support for JSON Web Tokens.
We can utilize this support to send MtM requests using the Authorization: Jwt ...
header.
note
This is the default authentication mechanism in Atoti Limits, but we will show how it is implemented nonetheless to provide a sample extension mechanism.
Using the default support
To use the native support, specify the following properties in both Atoti Limits and your connected server:
limits:
autoconfiguration:
service-principal: admin // this specifies the principal user designated to invoke MtM request with JWT MtM authentication
How it works
As described in Adding Custom Machine-to-Machine (MtM) Authentication, we need to add some custom implementations to our code.
1. Add a custom ILimitsRestClientBuilder
bean in the Connected Server and Atoti Limits.
This example is an implementation of ILimitsRestClientBuilder
, which uses JWT authentication:
@Getter
public class LimitsJwtRestClientBuilder implements ILimitsRestClientBuilder {
protected final RestClient.Builder restClientBuilder;
// We inject any services we need into our provider
public LimitsJwtRestClientBuilder(
// this is used to get or generate the JWT
IJwtService jwtService,
UserDetailsService userDetailsService,
// this is used to get the authorities of the service user
// we use this class to pull in properties, but you could use any property extraction mechanism
LimitsConnectionConfigurationProperties limitsConnectionConfigurationProperties
) {
// we build the client builder to be used for requests
this.restClientBuilder =
buildRestClient(jwtService, userDetailsService, limitsConnectionConfigurationProperties);
}
private RestClient.Builder buildRestClient(
IJwtService jwtService,
UserDetailsService userDetailsService,
LimitsConnectionConfigurationProperties limitsConnectionConfigurationProperties) {
String servicePrincipal =
limitsConnectionConfigurationProperties.getAutoconfiguration().getServicePrincipal();
if (servicePrincipal == null) {
throw new LimitsRuntimeException(
"You must specify the `limits.autoconfiguration.service-principal` property if you are using JWT machine-to-machine authentication!");
}
Collection<String> authorities =
userDetailsService.loadUserByUsername(servicePrincipal).getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toSet());
String jwt = jwtService.getToken(servicePrincipal, authorities);
// here is where we set the `Authorization: Jwt ...` header
return RestClient.builder().defaultHeader(AUTHORIZATION, "Jwt " + jwt);
}
}
2. Expose your custom ILimitsRestClientBuilder
bean in the Spring context
Once you have written your bean you can expose it to the Spring context.