Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MTLS Aliases endpoints to the discovery endpoint #2440

Merged
merged 4 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -370,4 +370,11 @@ public class DiscoveryConstants {
* If omitted, the default value is false.
*/
public static final String TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKEN = "tls_client_certificate_bound_access_tokens";

/**
* mtls_endpoint_aliases
* OPTIONAL. JSON Object containing a list of the aliases of the mTLS endpoints supported by the
* Authorization Server.
*/
public static final String MTLS_ENDPOINT_ALIASES = "mtls_endpoint_aliases";
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class DiscoveryUtil {

public static final String OIDC_USE_ENTITY_ID_AS_ISSUER_IN_DISCOVERY = "OAuth" +
".UseEntityIdAsIssuerInOidcDiscovery";
private static final String MUTUAL_TLS_ALIASES_ENABLED = "OAuth.MutualTLSAliases.Enabled";

/**
* Resident Idp entity id is honoured as the OIDC issuer location based on the configuration. This addresses
Expand All @@ -42,4 +43,18 @@ public static boolean isUseEntityIdAsIssuerInOidcDiscovery() {
}
return Boolean.parseBoolean(useEntityIdAsIssuerInDiscovery);
}

/**
* Check whether mutual TLS aliases are enabled. This is used to determine whether to display the mutual TLS
* endpoints in the well-known endpoint.
* @return true if mutual TLS aliases are enabled.
*/
public static boolean isMutualTLSAliasesEnabled() {

String mutualTLSAliasesEnabled = IdentityUtil.getProperty(MUTUAL_TLS_ALIASES_ENABLED);
if (StringUtils.isEmpty(mutualTLSAliasesEnabled)) {
RivinduM marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
RivinduM marked this conversation as resolved.
Show resolved Hide resolved
return Boolean.parseBoolean(mutualTLSAliasesEnabled);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public class OIDProviderConfigResponse {
private String deviceAuthorizationEndpoint;
private String webFingerEndpoint;
private Boolean tlsClientCertificateBoundAccessTokens;
private String mtlsTokenEndpoint;
private String mtlsPushedAuthorizationRequestEndpoint;

public String getIssuer() {
return issuer;
Expand Down Expand Up @@ -514,6 +516,16 @@ public void setTlsClientCertificateBoundAccessTokens(Boolean tlsClientCertificat
this.tlsClientCertificateBoundAccessTokens = tlsClientCertificateBoundAccessTokens;
}

public void setMtlsTokenEndpoint(String mtlsTokenEndpoint) {

this.mtlsTokenEndpoint = mtlsTokenEndpoint;
}

public void setMtlsPushedAuthorizationRequestEndpoint(String mtlsPushedAuthorizationRequestEndpoint) {

this.mtlsPushedAuthorizationRequestEndpoint = mtlsPushedAuthorizationRequestEndpoint;
}

public Map<String, Object> getConfigMap() {
Map<String, Object> configMap = new HashMap<String, Object>();
configMap.put(DiscoveryConstants.ISSUER.toLowerCase(), this.issuer);
Expand Down Expand Up @@ -581,6 +593,13 @@ public Map<String, Object> getConfigMap() {
configMap.put(DiscoveryConstants.WEBFINGER_ENDPOINT.toLowerCase(), this.webFingerEndpoint);
configMap.put(DiscoveryConstants.TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKEN.toLowerCase(),
this.tlsClientCertificateBoundAccessTokens);
if (DiscoveryUtil.isMutualTLSAliasesEnabled()) {
Map<String, String> mtlsAliases = new HashMap<String, String>();
mtlsAliases.put(DiscoveryConstants.TOKEN_ENDPOINT.toLowerCase(), this.mtlsTokenEndpoint);
mtlsAliases.put(DiscoveryConstants.PUSHED_AUTHORIZATION_REQUEST_ENDPOINT.toLowerCase(),
this.mtlsPushedAuthorizationRequestEndpoint);
configMap.put(DiscoveryConstants.MTLS_ENDPOINT_ALIASES, mtlsAliases);
}
return configMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ public OIDProviderConfigResponse buildOIDProviderConfig(OIDProviderRequest reque
providerConfig.setWebFingerEndpoint(OAuth2Util.OAuthURL.getOidcWebFingerEPUrl());
providerConfig.setTlsClientCertificateBoundAccessTokens(OAuth2Util.getSupportedTokenBindingTypes()
.contains(OAuth2Constants.TokenBinderType.CERTIFICATE_BASED_TOKEN_BINDER));
providerConfig.setMtlsTokenEndpoint(OAuth2Util.OAuthURL.getOAuth2MTLSTokenEPUrl());
providerConfig.setMtlsPushedAuthorizationRequestEndpoint(OAuth2Util.OAuthURL.getOAuth2MTLSParEPUrl());
return providerConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ public static SubjectType fromValue(String text) {
public static final String RENEW_TOKEN_WITHOUT_REVOKING_EXISTING_ENABLE_CONFIG =
"OAuth.JWT.RenewTokenWithoutRevokingExisting.Enable";
public static final String OAUTH_BUILD_ISSUER_WITH_HOSTNAME = "OAuth.BuildIssuerWithHostname";
public static final String MTLS_HOSTNAME = "OAuth.MutualTLSAliases.Hostname";

public static final String REQUEST_BINDING_TYPE = "request";
public static final String ORG_ID = "org_id";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,18 @@ public static String getOAuth2TokenEPUrl() {
return buildUrl(OAUTH2_TOKEN_EP_URL, OAuthServerConfiguration.getInstance()::getOAuth2TokenEPUrl);
}

public static String getOAuth2MTLSParEPUrl() {

return buildUrlWithHostname(OAUTH2_PAR_EP_URL, OAuthServerConfiguration.getInstance()::getOAuth2ParEPUrl,
IdentityUtil.getProperty(OAuthConstants.MTLS_HOSTNAME));
}

public static String getOAuth2MTLSTokenEPUrl() {

return buildUrlWithHostname(OAUTH2_TOKEN_EP_URL, OAuthServerConfiguration.getInstance()::
getOAuth2TokenEPUrl, IdentityUtil.getProperty(OAuthConstants.MTLS_HOSTNAME));
}

/**
* This method is used to get the resolved URL for the OAuth2 Registration Endpoint.
*
Expand Down Expand Up @@ -1642,6 +1654,28 @@ private static String buildUrl(String defaultContext, Supplier<String> getValueF
return buildServiceUrl(defaultContext, oauth2EndpointURLInFile);
}

/**
* Builds a URL with a given context in both the tenant-qualified url supported mode and the legacy mode.
* Returns the absolute URL build from the default context in the tenant-qualified url supported mode. Gives
* precedence to the file configurations in the legacy mode and returns the absolute url build from file
* configuration context.
*
* @param defaultContext Default URL context.
* @param getValueFromFileBasedConfig File-based Configuration.
* @param hostname hostname of the service
* @return Absolute URL.
*/
private static String buildUrlWithHostname(String defaultContext, Supplier<String> getValueFromFileBasedConfig,
String hostname) {

String oauth2EndpointURLInFile = null;
if (getValueFromFileBasedConfig != null) {
oauth2EndpointURLInFile = getValueFromFileBasedConfig.get();
}
return hostname != null ? buildServiceUrlWithHostname(defaultContext, oauth2EndpointURLInFile, hostname) :
buildServiceUrl(defaultContext, oauth2EndpointURLInFile);
}

/**
* Returns the public service url given the default context and the url picked from the configuration based on
* the 'tenant_context.enable_tenant_qualified_urls' mode set in deployment.toml.
Expand Down Expand Up @@ -1673,6 +1707,39 @@ public static String buildServiceUrl(String defaultContext, String oauth2Endpoin
}
}

/**
* Returns the public service url given the default context and the url picked from the configuration based on
* the 'tenant_context.enable_tenant_qualified_urls' mode set in deployment.toml.
*
* @param defaultContext default url context path
* @param oauth2EndpointURLInFile url picked from the file configuration
* @param hostname hostname of the service
* @return absolute public url of the service if 'enable_tenant_qualified_urls' is 'true', else returns the url
* from the file config
*/
public static String buildServiceUrlWithHostname(String defaultContext, String oauth2EndpointURLInFile,
String hostname) {

if (IdentityTenantUtil.isTenantQualifiedUrlsEnabled()) {
try {
String organizationId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getOrganizationId();
return ServiceURLBuilder.create().addPath(defaultContext).setOrganization(organizationId)
.buildURL(hostname).getAbsolutePublicURL();
RivinduM marked this conversation as resolved.
Show resolved Hide resolved
} catch (URLBuilderException e) {
throw new OAuthRuntimeException("Error while building url for context: " + defaultContext);
RivinduM marked this conversation as resolved.
Show resolved Hide resolved
}
} else if (StringUtils.isNotBlank(oauth2EndpointURLInFile)) {
// Use the value configured in the file.
return oauth2EndpointURLInFile;
}
// Use the default context.
try {
return ServiceURLBuilder.create().addPath(defaultContext).buildURL(hostname).getAbsolutePublicURL();
RivinduM marked this conversation as resolved.
Show resolved Hide resolved
} catch (URLBuilderException e) {
throw new OAuthRuntimeException("Error while building url for context: " + defaultContext);
}
}

private static boolean isNotSuperTenant(String tenantDomain) {

return (StringUtils.isNotBlank(tenantDomain) &&
Expand Down
Loading