in token-service/src/main/java/com/google/solutions/tokenservice/oauth/mtls/XlbMtlsClientCredentialsFlow.java [146:221]
public MtlsClientAttributes getVerifiedClientAttributes(AuthenticationRequest request)
{
Preconditions.checkNotNull(request, "request");
//
// Verify that the client presented a certificate and that the
// load balancer reported it as "verified".
//
var headers = this.request.headers();
if (!canAuthenticate(request))
{
throw new ForbiddenException(
"The request did not include a client certificate");
}
if (!"true".equalsIgnoreCase(headers.get(this.options.clientCertChainVerifiedHeaderName())))
{
this.logAdapter
.newErrorEntry(
LogEvents.API_TOKEN,
"The client certificate did not pass verification")
.addLabels(this::addHeaderLabels)
.write();
throw new ForbiddenException("The client certificate did not pass verification");
}
this.logAdapter
.newInfoEntry(
LogEvents.API_TOKEN,
"The client certificate was verified by the load balancer")
.addLabels(this::addHeaderLabels)
.write();
//
// The load balancer verified the certificate, and we can now read the other
// headers to obtain the certificate attributes.
//
// NB. There's no way for us to confirm that it was really the load balancer
// that added the header. But if the application has been deployed correctly,
// then there shouldn't be any way for clients to sidestep the load balancer.
//
//
// Read whatever header has been configured to contain the OAuth client ID.
//
var clientId = headers.get(this.options.clientIdHeaderName());
if (Strings.isNullOrEmpty(clientId)) {
throw new ForbiddenException(
String.format(
"The client presented a valid certificate, but the header '%s' does not contain a client ID",
this.options.clientIdHeaderName()));
}
this.logAdapter
.newInfoEntry(
LogEvents.API_TOKEN,
String.format("Authenticated client '%s' using mTLS headers", clientId))
.addLabels(this::addHeaderLabels)
.write();
//
// Return all attributes from HTTP headers. Note that some
// attributes might be empty.
//
return new MtlsClientAttributes(
clientId,
headers.get(this.options.clientCertSpiffeIdHeaderName),
decodeSanHeader(headers.get(this.options.clientCertDnsSansHeaderName)),
decodeSanHeader(headers.get(this.options.clientCertUriSansHeaderName)),
headers.get(this.options.clientCertHashHeaderName),
headers.get(this.options.clientCertSerialNumberHeaderName),
parseIfNotNull(headers.get(this.options.clientCertNotBeforeHeaderName)),
parseIfNotNull(headers.get(this.options.clientCertNotAfterHeaderName)));
}