feat: RFC 8705 mutual-TLS client authentication for CF app instance identity - #3972
feat: RFC 8705 mutual-TLS client authentication for CF app instance identity#3972rkoster wants to merge 110 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds RFC 8705 mutual-TLS client authentication support for Cloud Foundry app instance identity by introducing a dedicated /oauth/mtls/token endpoint, validating instance certificates against per-client CA configuration, and enriching issued JWTs with CF identity claims derived from certificate subject fields. It also updates OIDC discovery to advertise mTLS endpoint aliases and tls_client_auth as a supported token endpoint authentication method.
Changes:
- Introduces
/oauth/mtls/tokenwith a dedicated Spring Security filter chain and request-to-certificate mapping viaClientCertificateMapper. - Adds TLS client certificate validation (
TlsClientAuthentication) and a token enhancer (MtlsClaimsEnhancer) to emitcnf.x5t#S256plus configured subject-derived claims. - Extends client auth method support across model/constants and OIDC discovery metadata (
tls_client_auth,mtls_endpoint_aliases).
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| server/src/test/java/org/cloudfoundry/identity/uaa/oauth/tls/TlsClientAuthenticationTest.java | Adds unit coverage for null inputs and malformed CA handling in TLS cert validation. |
| server/src/test/java/org/cloudfoundry/identity/uaa/oauth/tls/MtlsClaimsEnhancerTest.java | Verifies OU/CN claim extraction and cnf.x5t#S256 behavior for mTLS tokens. |
| server/src/test/java/org/cloudfoundry/identity/uaa/oauth/tls/ClientCertificateMapperFilterTest.java | Confirms servlet filter registration for mapping XFCC to request X509Certificate attribute on /oauth/mtls/*. |
| server/src/test/java/org/cloudfoundry/identity/uaa/oauth/provider/client/ClientCredentialsTokenGranterTests.java | Ensures tls_client_auth is allowed for client_credentials. |
| server/src/test/java/org/cloudfoundry/identity/uaa/authentication/UaaClientAuthenticationProviderTest.java | Updates provider wiring to include TlsClientAuthentication. |
| server/src/test/java/org/cloudfoundry/identity/uaa/authentication/ClientDetailsAuthenticationProviderTests.java | Adds tests for mtls path detection and TLS config deserialization behavior. |
| server/src/test/java/org/cloudfoundry/identity/uaa/account/OpenIdConnectEndpointsTest.java | Validates discovery document includes mtls_endpoint_aliases.token_endpoint. |
| server/src/main/java/org/cloudfoundry/identity/uaa/web/FilterChainOrder.java | Adds a new security chain order slot (OAUTH_11) for the mTLS token endpoint chain. |
| server/src/main/java/org/cloudfoundry/identity/uaa/SpringServletXmlFiltersConfiguration.java | Registers ClientCertificateMapper filter for /oauth/mtls/*. |
| server/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenEndpoint.java | Expands token endpoint mapping to include /oauth/mtls/token. |
| server/src/main/java/org/cloudfoundry/identity/uaa/oauth/tls/TlsClientAuthentication.java | Adds per-client CA-based PKIX validation and request certificate extraction helper. |
| server/src/main/java/org/cloudfoundry/identity/uaa/oauth/tls/MtlsClaimsEnhancer.java | Implements JWT enrichment from cert subject + cnf.x5t#S256 for the mTLS flow. |
| server/src/main/java/org/cloudfoundry/identity/uaa/oauth/provider/client/ClientCredentialsTokenGranter.java | Allows tls_client_auth as a valid auth method for client credentials. |
| server/src/main/java/org/cloudfoundry/identity/uaa/oauth/beans/OauthEndpointSecurityConfiguration.java | Adds dedicated security filter chain for /oauth/mtls/token (stateless + CSRF disabled). |
| server/src/main/java/org/cloudfoundry/identity/uaa/oauth/beans/OauthEndpointBeanConfiguration.java | Wires TlsClientAuthentication into ClientDetailsAuthenticationProvider bean construction. |
| server/src/main/java/org/cloudfoundry/identity/uaa/authentication/ClientDetailsAuthenticationProvider.java | Detects mTLS path, validates certs, and parses per-client TLS configuration from additional info. |
| server/src/main/java/org/cloudfoundry/identity/uaa/account/OpenIdConnectEndpoints.java | Populates mtls_endpoint_aliases in OIDC discovery. |
| server/build.gradle.kts | Adds dependency on the Gorouter client certificate mapper (Jakarta). |
| model/src/test/resources/org/cloudfoundry/identity/uaa/account/OpenIdConfiguration.json | Updates fixture to include tls_client_auth in supported auth methods. |
| model/src/test/java/org/cloudfoundry/identity/uaa/constants/ClientAuthenticationTest.java | Adds tests for tls_client_auth support, secret requirements, and validity rules. |
| model/src/test/java/org/cloudfoundry/identity/uaa/client/UaaClientDetailsTest.java | Adds JSON round-trip test for TLS client auth config and adjusts hashCode assertion. |
| model/src/test/java/org/cloudfoundry/identity/uaa/client/TlsClientAuthConfigurationTest.java | Adds unit tests for TLS auth config JSON round-tripping and equality semantics. |
| model/src/test/java/org/cloudfoundry/identity/uaa/account/OpenIdConfigurationTests.java | Updates supported auth methods expectations and adds tests for mTLS aliases field. |
| model/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/TokenConstants.java | Exposes CLIENT_AUTH_TLS_CLIENT_AUTH constant. |
| model/src/main/java/org/cloudfoundry/identity/uaa/constants/ClientAuthentication.java | Adds TLS_CLIENT_AUTH constant and updates supported/valid method logic and calculation. |
| model/src/main/java/org/cloudfoundry/identity/uaa/client/UaaClientDetails.java | Introduces tlsClientAuthConfiguration field and includes it in equals/hashCode. |
| model/src/main/java/org/cloudfoundry/identity/uaa/client/TlsClientAuthConfiguration.java | Adds model for trusted CA PEM + claim mapping configuration. |
| model/src/main/java/org/cloudfoundry/identity/uaa/account/OpenIdConfiguration.java | Adds mtls_endpoint_aliases and includes tls_client_auth in supported methods. |
Add TlsClientAuthConfiguration field serialized as tls-client-auth-ca in client JSON, following the clientJwtConfig pattern. Includes getter/setter, copy constructor support, equals/hashCode. Fix fragile isPositive() hash code assertion to isNotZero().
…tailsAuthenticationProvider
…dpoint The BOSH ERB template emits 'mtls.endpoint' (from the nested mtls.endpoint YAML block) but the @value annotation was reading 'uaa.mtls_endpoint_path', a key never emitted by the template. Align the annotation to the actual Spring property so operator-configured paths are honoured.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 60 changed files in this pull request and generated 5 comments.
Suppressed comments (9)
Previously missed (8) — in code that hasn't changed since the last review.
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminBootstrap.java:223
- The documented
oauth.clientsbootstrap path bypassesvalidateTlsClientAuthClaimConfig. It can therefore persist invalid fields, regexes, templates, or required-claim references that the admin APIs reject; those values later produce missing claims or token-time failures. Apply the same validation before registering the client.
ClientAdminEndpointsValidator.checkMtlsClientConfigAllowed(client.getAdditionalInformation(), mtlsEnabled, clientId);
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminEndpointsValidator.java:413
- This early return also accepts
tls-client-auth-sub-template,tls-client-auth-aud-templates, ortls-client-auth-required-claimswhen no mappings key exists. Such templates can never resolve, while required claims make every authentication fail. Reject dependent claim settings unless mappings are present; only a configuration with none of these keys should be a no-op.
if (additionalInfo == null
|| !additionalInfo.containsKey(TlsClientAuthConfiguration.TLS_CLIENT_AUTH_CLAIM_MAPPINGS)) {
return;
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminEndpointsValidator.java:458
- A regex with no capture group is accepted here, but
matchFirstOuemits a value only whengroupCount() >= 1and then reads group 1. Thus a syntactically valid pattern such as^app:.*$is accepted at registration yet silently produces no claim. Either reject patterns without a capture group here or define runtime semantics that use the full match.
Pattern.compile(pattern);
server/src/main/java/org/cloudfoundry/identity/uaa/oauth/tls/TlsClientAuthentication.java:249
patternis applied only tosubject_ou; mappings forsubject_cnandsubject_oignore a supplied pattern and copy the complete value. The validator and documentation allow a pattern on every mapping, so accepted CN/O configurations can emit a different claim than configured (and fail required-claim checks). Apply the same matching semantics to all supported fields, or reject patterns for fields where they are unsupported.
String value = switch (mapping.getField()) {
case "subject_cn" -> cn;
case "subject_ou" -> matchFirstOu(ous, mapping.getPattern());
case "subject_o" -> extractRdnValue(dn, "O");
default -> null;
server/src/main/java/org/cloudfoundry/identity/uaa/account/OpenIdConnectEndpoints.java:23
mtls.endpointonly changes the URL published in discovery; the MVC mapping, security matcher, and servlet-filter path guards remain hard-coded to/oauth/mtls/token. Any non-default value therefore advertises a nonexistent endpoint. Remove this configurability or wire one validated path through every route/matcher.
@Value("${mtls.endpoint:/oauth/mtls/token}")
private String mtlsEndpointPath = "/oauth/mtls/token";
docs/UAA-Client-Authentication.md:125
- This documents
token-endpoint-auth-methodas required and as selecting mTLS, but the repository has no code that reads this client property; bootstrap merely leaves it as unused additional information, and authentication is selected from the request path plus CA presence. Either implement persistence/enforcement of this metadata or remove the property from the required configuration so operators are not relying on a no-op.
| `token-endpoint-auth-method: tls_client_auth` | yes | Selects mTLS client authentication for this client. |
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminEndpointsValidator.java:497
- Null and blank audience templates are silently accepted here, but
MtlsClaimsEnhancercallsrenderTemplate(template, ...)unconditionally; a null element throws attemplate.length(), while a blank element can produce an invalid emptyaudvalue. Reject null/blank list entries during client validation.
for (String template : audTemplates) {
if (template != null && !template.isBlank()) {
checkTemplateLength(template, TlsClientAuthConfiguration.TLS_CLIENT_AUTH_AUD_TEMPLATES, clientId);
validateTemplatePlaceholders(template, declaredClaims,
TlsClientAuthConfiguration.TLS_CLIENT_AUTH_AUD_TEMPLATES, clientId);
}
docs/UAA-Client-Authentication.md:129
- The field list omits the supported
subject_ovalue, even though validation and extraction accept it. Operators following this table cannot discover or correctly configure organization-subject mappings; includesubject_oin the documented set.
| `tls-client-auth-claim-mappings` | no | List of `{field, pattern, claim}` mappings from certificate subject fields (`subject_cn`, `subject_ou`) to JWT claim names, optionally extracting a capture group via `pattern`. |
model/src/main/java/org/cloudfoundry/identity/uaa/client/UaaClientDetails.java:110
- The copy constructor deletes a flat mTLS CA received through the client-admin API. Because the typed field is
@JsonIgnore, deserialization leaves it null and storestls-client-auth-cainadditionalInformation; line 107 copies that map, then this null setter removes the key.ClientAdminEndpointsValidatorconstructs this copy before persisting it, so API-created mTLS clients lose their CA configuration. Preserve the copied map when the typed field is null.
this.setTlsClientAuthConfiguration(uaa.getTlsClientAuthConfiguration());
…bled OpenIdConfiguration's token_endpoint_auth_methods_supported unconditionally included tls_client_auth, regardless of uaa.mtls-enabled -- a discovery client on a deployment with mTLS disabled (the default) would select an authentication method this server cannot actually perform, since such deployments never request peer certificates at the TLS layer nor allow tls-client-auth-ca to be configured on any client. Adds a new 3-arg constructor overload accepting mtlsEnabled, which filters tls_client_auth out of tokenAMR when false. The existing 2-arg constructor is unchanged in behavior (delegates with mtlsEnabled=true), preserving all existing callers/tests. Addresses PR review comment on OpenIdConfiguration.java:25.
…abled getOpenIdConfiguration unconditionally set mtls_endpoint_aliases pointing at /oauth/mtls/token, even on deployments with uaa.mtls-enabled=false (the default), where that endpoint cannot actually authenticate a client via a certificate -- making the discovery document contradict the deployment's actual capabilities. OpenIdConnectEndpoints now takes a uaa.mtls-enabled-injected constructor argument, passed through to OpenIdConfiguration's new mtlsEnabled-aware constructor, and only sets mtls_endpoint_aliases when true. Addresses PR review comment on OpenIdConnectEndpoints.java:40.
… BouncyCastleFipsProvider ensureJsseProviderRegistered already verified an existing same-named BCJSSE provider (an earlier review round), but the BCFIPS crypto-provider registration just above it still only checked for presence under that name, not type -- the same provider-name substitution gap. BouncyCastleFipsProvider has no FIPS/non-FIPS mode distinction (unlike BouncyCastleJsseProvider) -- it IS inherently the FIPS-only crypto provider by construction -- so only an instanceof check is needed here, not a second mode check. Addresses PR review comment on MtlsClientAuthTomcatCustomizer.java:119.
…ing invariant Both discovery gates are driven by the same uaa.mtls-enabled flag today, but nothing previously asserted they stay consistent with each other -- a future edit to one call site without the other would silently reintroduce a contradictory discovery document. Adds an explicit test for both the enabled and disabled cases.
Previously stated the dedicated /oauth/mtls/token endpoint routing meant 'without changing behavior for every other client on /oauth/token' -- this conflated endpoint-level authentication scoping (genuinely dedicated) with the underlying TLS-handshake configuration, which MtlsClientAuthTomcatCustomizer applies connector-wide via certificateVerification=optionalNoCA. Every TLS handshake to this UAA instance requests a client certificate when uaa.mtls-enabled is true, regardless of the endpoint ultimately routed to. Addresses PR review comment on docs/UAA-Client-Authentication.md:61.
TokenEndpointDocs previously only documented /oauth/token's various grant types and client authentication methods -- the mTLS token endpoint added by this PR had no corresponding REST Docs coverage, so generated API documentation omitted its request format, authentication requirements, and response shape entirely. Adds a client_credentials + tls_client_auth documentation test: generates a CA and a leaf certificate, configures a dedicated documentation client with tls-client-auth-ca, presents the leaf certificate via the servlet request attribute the real TLS handshake (or XFCC mapper) would populate, and documents the resulting token response. Adds testImplementation(libs.bouncyCastlePkixFips) to uaa/build.gradle.kts (certificate-generation classes not previously on this module's test compile classpath), mirroring the existing declaration in server/build.gradle.kts for the same purpose. Addresses PR review comment on UaaTokenEndpoint.java:34.
…ndered API docs TokenEndpointDocs.getTokenUsingClientCredentialGrantWithTlsClientAuth (added in 1babf25) generates REST Docs snippets, but index.html.md.erb was never updated to render them -- the generated customer-facing API documentation would have continued to omit /oauth/mtls/token entirely, the exact gap the PR review comment on UaaTokenEndpoint.java:34 was raised to close. Adds a 'Mutual TLS Client Authentication' subsection under Client Credentials Grant, following the same curl-request/http-request/ http-response/form-parameters/response-fields render() pattern already used for the Client Secret/Authorization Header/Client Assertion variants, plus a short prose note and a link to docs/UAA-Client-Authentication.md for deployment details.
…t tests a7b77e3/bf6149ae8 made tls_client_auth and mtls_endpoint_aliases only advertised in the OIDC discovery document when uaa.mtls-enabled is true (default false), correctly closing a gap where a discovery client could select an authentication method the server can't actually perform. Three pre-existing tests in the uaa module -- OpenIdConnectEndpointDocs (a REST Docs test, which broke the generate-api-docs CI job with a SnippetException since the documented mtls_endpoint_aliases.token_endpoint field was no longer present in the default-config response) and OpenIdConnectEndpointsMockMvcTests/OpenIdConnectEndpointsMockMvcZonePathTests -- were not updated at the time and started failing under the default (disabled) configuration once that fix landed, since they assert on tls_client_auth/mtls_endpoint_aliases being present unconditionally. Adds @TestPropertySource(properties = "uaa.mtls-enabled=true") to all three, matching the same pattern already used in TokenEndpointDocs, so these tests continue to exercise and document the mTLS-enabled discovery document shape they were originally written for.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 63 changed files in this pull request and generated 4 comments.
Suppressed comments (4)
Previously missed (3) — in code that hasn't changed since the last review.
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminBootstrap.java:223
- Bootstrapped
oauth.clientsbypass the two validators that callvalidateTlsClientAuthClaimConfig. This path only checks the feature flag, so an invalid regex or null mapping is persisted and later fails token issuance inside certificate-claim extraction. Validate the claim configuration here before registering the client.
client.setAdditionalInformation(info);
ClientAdminEndpointsValidator.checkMtlsClientConfigAllowed(client.getAdditionalInformation(), mtlsEnabled, clientId);
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminEndpointsValidator.java:413
- This early return also skips validation when
tls-client-auth-required-claimsis configured without any claim mappings. Such a client is accepted but can never authenticate because extraction always yields an empty map, so every required claim fails. Treat missing mappings as an empty declaration set and continue validating dependent properties.
public static void validateTlsClientAuthClaimConfig(Map<String, Object> additionalInfo, String clientId) {
if (additionalInfo == null
|| !additionalInfo.containsKey(TlsClientAuthConfiguration.TLS_CLIENT_AUTH_CLAIM_MAPPINGS)) {
return;
server/src/main/java/org/cloudfoundry/identity/uaa/zone/ZoneEndpointsClientDetailsValidator.java:60
- Presence of the map key is not equivalent to a configured CA. A blank/null
tls-client-auth-cacurrently bypasses the required-secret check, so the zone API accepts a secretless client that can never passTlsClientAuthConfiguration.isConfiguredduring authentication. Base this decision on a nonblank, valid CA configuration instead.
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminEndpointsValidator.java:463
- A syntactically valid pattern with no capture group is accepted here, but
matchFirstOuonly emitsgroup(1). For example,^app:.*$saves successfully yet silently produces no claim (and can make required-claim authentication permanently fail). Reject patterns that do not declare at least one capture group.
String pattern = mapping.getPattern();
if (pattern != null && !pattern.isBlank()) {
try {
Pattern.compile(pattern);
} catch (PatternSyntaxException e) {
throw new InvalidClientDetailsException(
"tls-client-auth-claim-mappings entry has an invalid pattern '" + pattern
+ "' for client_id=" + clientId + ": " + e.getMessage(), e);
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 70 out of 70 changed files in this pull request and generated 2 comments.
Suppressed comments (3)
model/src/main/java/org/cloudfoundry/identity/uaa/client/UaaClientDetails.java:110
- Copying a JDBC/JSON-loaded
UaaClientDetailsdrops its mTLS CA: such instances have the flat configuration only inadditionalInformationand a null typed field, so this setter removes the key copied on line 107.InMemoryClientDetailsService.addClientDetailsuses this copy constructor, leaving the copied client unable to authenticate. Only invoke the setter when the typed value is non-null so the flat representation is preserved.
this.setTlsClientAuthConfiguration(uaa.getTlsClientAuthConfiguration());
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminEndpointsValidator.java:420
- Returning as soon as
tls-client-auth-claim-mappingsis absent also skips validation oftls-client-auth-required-claims. A client can therefore persist required claims without any mapping capable of producing them; authentication then always fails because extraction returns an empty map. Parse an absent mapping list as empty and continue validating dependent properties so this invalid configuration is rejected at creation time.
public static void validateTlsClientAuthClaimConfig(Map<String, Object> additionalInfo, String clientId) {
if (additionalInfo == null
|| !additionalInfo.containsKey(TlsClientAuthConfiguration.TLS_CLIENT_AUTH_CLAIM_MAPPINGS)) {
return;
server/src/main/java/org/cloudfoundry/identity/uaa/client/ClientAdminEndpointsValidator.java:465
- Compiling the regex is insufficient validation for the runtime contract.
TlsClientAuthentication.matchFirstOuonly emitsgroup(1), so a valid regex with no capture group is accepted here but silently produces no claim. In addition, patterns onsubject_cnandsubject_oare accepted here but ignored by extraction. Either apply capture-group patterns consistently to all supported fields or reject configurations that runtime cannot honor.
String pattern = mapping.getPattern();
if (pattern != null && !pattern.isBlank()) {
try {
Pattern.compile(pattern);
| Object tlsClientAuthCa = clientDetails.getAdditionalInformation() | ||
| .get(TlsClientAuthConfiguration.TLS_CLIENT_AUTH_CA); | ||
| boolean hasTlsClientAuthCa = tlsClientAuthCa instanceof String && !((String) tlsClientAuthCa).isBlank(); |
| if (additionalInfo.containsKey(TOKEN_ENDPOINT_AUTH_METHOD)) { | ||
| throw new InvalidClientDetailsException( | ||
| "token-endpoint-auth-method is not supported; configure tls-client-auth-ca to enable mTLS for client_id=" | ||
| + clientId); |
Summary
Implements RFC 8705 mutual-TLS client
authentication for Cloud Foundry app instance identity, enabling workload identity
federation with AWS, GCP, Azure, and any OIDC-aware service.
CF app instances already receive a short-lived X.509 certificate from the Diego
Cell (
instance.crt/instance.key). This change lets an app exchange that certfor a UAA JWT containing verified
app_guid,space_guid,org_guid, andcf_instance_guidclaims — without secrets or user credentials.How it works
Changes (this PR — 18 commits)
Model layer:
ClientAuthentication: addtls_client_authconstantTokenConstants: addCLIENT_AUTH_TLS_CLIENT_AUTHTlsClientAuthConfiguration: per-client CA PEM + claim-mapping modelUaaClientDetails: addtlsClientAuthConfigurationfieldOpenIdConfiguration: addmtls_endpoint_aliasesto OIDC discoveryServer layer:
ClientDetailsAuthenticationProvider:isTlsClientAuth(),validateTlsClientAuth(),getTlsClientAuthConfiguration()— handles in-memory, Map (Jackson), and flat String PEM (BOSH) config formsTlsClientAuthentication: PKIX cert chain validation against per-client CAClientCertificateMapperregistration:SpringServletXmlFiltersConfigurationregisters thejava-buildpack-client-certificate-mapper-jakartafilter for/oauth/mtls/*to materialiseX-Forwarded-Client-Certas ajakarta.servlet.request.X509CertificateattributeClientCredentialsTokenGranter: allowtls_client_authalongsideclient_secretMtlsClaimsEnhancer:UaaTokenEnhancerthat reads cert subject OU fields and maps them to JWT claims per per-client configuration; handles DB-loaded clients (readsadditionalInformationdirectly) and Diego multi-valued RDNsFilterChainOrder.OAUTH_11+mtlsTokenEndpointSecurity: dedicated security filter chain for/oauth/mtls/tokenwith CSRF disabledUaaTokenEndpoint: add/oauth/mtls/tokento@RequestMappingmtls_endpoint_aliasesDeployment notes
Requires the Gorouter to be configured with
forwarded_client_cert: sanitize_setso it validates the TLS session cert and injects it as
X-Forwarded-Client-Cert.The UAA client for an app must be configured with:
tls-client-auth-trusted-proxy-caswitches this client to the Gorouter/XFCC-forwarding-onlytopology: UAA then requires the
X-Forwarded-Client-Certheader to actually be present and itsimmediate TLS peer to have presented a certificate signed by that CA during the handshake --
preventing a direct caller (bypassing the Gorouter) from replaying a harvested certificate it
doesn't hold the private key for, or a direct connection from being silently accepted instead.
For a client that connects to UAA directly (e.g. permitted by Application Security Group
configuration, bypassing the Gorouter), omit this property entirely -- configuring it at all
makes the client reject direct connections. See
docs/UAA-Client-Authentication.mdfor both cases; two separate UAA clients are needed to support both patterns for the same
workload.
Proof of concept
End-to-end verified on a real CF deployment: a Go app pushes its Diego instance cert
to
POST /oauth/mtls/token, and the returned JWT contains:{ "app_guid": "b0bff1c2-a258-4060-981d-601f22e6bcf8", "space_guid": "02700fa7-8db7-4598-b015-9a5fc73d4656", "org_guid": "8deb6c47-8460-4501-8a86-246b774d97e4", "cf_instance_guid": "86bf36e4-af79-4d7a-6484-0d89", "client_auth_method": "tls_client_auth", "cnf": { "x5t#S256": "rk4P4d0DXNJDpZeOotKRUzmoaomqSqPQn8OzyKQhMuw" } }All GUIDs verified against
cf app,cf org, andcf space --guid.Related
cloudfoundry/uaa-release