mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-28 04:13:22 -04:00
Redirect Wildcard changes and more https checks to secure-client-executor (#46082)
Closes #45587 Signed-off-by: Marie Daly <marie.daly1@ibm.com>
This commit is contained in:
parent
0669a7eb14
commit
7d6108d4b9
8 changed files with 270 additions and 25 deletions
|
|
@ -14,6 +14,18 @@ It was also not aligned with how other script-based features work in {project_na
|
|||
|
||||
If you have existing JavaScript-based policies, make sure to enable the `scripts` feature when starting {project_name}.
|
||||
|
||||
=== Stricter Validation for Client URIs (secure-client-uris)
|
||||
The 'secure-client-uris' client policy executor has been updated to enforce stricter validation on Client URIs. This aligns with FAPI 2.0 security requirements by mandating TLS (HTTPS) for client endpoints.
|
||||
|
||||
HTTPS Enforcement: The following URIs must now use the https scheme. Existing clients configured with http in these fields will fail validation during updates:
|
||||
'Post logout redirect URIs', 'Logo URL', 'Policy URL', and 'Terms of Service URL'.
|
||||
|
||||
Expanded Wildcard Support: The + wildcard character is now allowed in 'Valid post logout redirect URIs' and 'Web origins'.
|
||||
Configuring + defers validation to the client's standard 'Valid redirect URIs'. Since redirect URIs are already checked for HTTPS, using the wildcard maintains FAPI 2.0 compliance while reducing configuration duplication.
|
||||
|
||||
Administrators must ensure that all configured URIs for the fields listed above use https. Clients attempting to update or register with http in these fields will fail validation when using the 'secure-client-uris' executor.
|
||||
|
||||
|
||||
// ------------------------ Notable changes ------------------------ //
|
||||
== Notable changes
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ public final class Constants {
|
|||
// multiple values into single string
|
||||
public static final String CFG_DELIMITER = "##";
|
||||
|
||||
public static final String INCLUDE_REDIRECTS = "+";
|
||||
|
||||
// Better performance to use this instead of String.split
|
||||
public static final Pattern CFG_DELIMITER_PATTERN = Pattern.compile("\\s*" + CFG_DELIMITER + "\\s*");
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ public final class OIDCConfigAttributes {
|
|||
public static final String JWT_AUTHORIZATION_GRANT_ENABLED = "oauth2.jwt.authorization.grant.enabled";
|
||||
public static final String JWT_AUTHORIZATION_GRANT_IDP = "oauth2.jwt.authorization.grant.idp";
|
||||
|
||||
|
||||
public static final String LOGO_URI = "logoUri";
|
||||
public static final String TOS_URI = "tosUri";
|
||||
public static final String POLICY_URI = "policyUri";
|
||||
private OIDCConfigAttributes() {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ package org.keycloak.protocol.oidc.utils;
|
|||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Pattern;
|
||||
|
|
@ -214,4 +216,29 @@ public class RedirectUtils {
|
|||
}
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
public static Set<String> resolveUrlsWithRedirects(KeycloakSession session, List<String> origUrls,
|
||||
String rootUrl, List<String> redirectUris, boolean returnAsOrigins) {
|
||||
|
||||
Set<String> refactoredUrls = (origUrls != null) ? new HashSet<>(origUrls) : new HashSet<>();
|
||||
if (refactoredUrls.contains(Constants.INCLUDE_REDIRECTS)) {
|
||||
refactoredUrls.remove(Constants.INCLUDE_REDIRECTS);
|
||||
|
||||
Set<String> redirectsToProcess = (redirectUris != null) ? new HashSet<>(redirectUris) : Collections.emptySet();
|
||||
for (String redirectUri : resolveValidRedirects(session, rootUrl, redirectsToProcess)) {
|
||||
if (isValidScheme(redirectUri)) {
|
||||
if (returnAsOrigins) {
|
||||
refactoredUrls.add(UriUtils.getOrigin(redirectUri));
|
||||
} else {
|
||||
refactoredUrls.add(redirectUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return refactoredUrls;
|
||||
}
|
||||
|
||||
private static boolean isValidScheme(String url) {
|
||||
return url != null && (url.startsWith("http://") || url.startsWith("https://"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Set;
|
|||
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
/**
|
||||
|
|
@ -29,15 +30,13 @@ import org.keycloak.models.KeycloakSession;
|
|||
*/
|
||||
public class WebOriginsUtils {
|
||||
|
||||
public static final String INCLUDE_REDIRECTS = "+";
|
||||
|
||||
public static Set<String> resolveValidWebOrigins(KeycloakSession session, ClientModel client) {
|
||||
Set<String> origins = new HashSet<>();
|
||||
if (client.getWebOrigins() != null) {
|
||||
origins.addAll(client.getWebOrigins());
|
||||
}
|
||||
if (origins.contains(INCLUDE_REDIRECTS)) {
|
||||
origins.remove(INCLUDE_REDIRECTS);
|
||||
if (origins.contains(Constants.INCLUDE_REDIRECTS)) {
|
||||
origins.remove(Constants.INCLUDE_REDIRECTS);
|
||||
for (String redirectUri : RedirectUtils.resolveValidRedirects(session, client.getRootUrl(), client.getRedirectUris())) {
|
||||
if (redirectUri.startsWith("http://") || redirectUri.startsWith("https://")) {
|
||||
origins.add(UriUtils.getOrigin(redirectUri));
|
||||
|
|
|
|||
|
|
@ -17,16 +17,19 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.executor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.models.CibaConfig;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.protocol.oidc.OIDCConfigAttributes;
|
||||
import org.keycloak.protocol.oidc.utils.RedirectUtils;
|
||||
import org.keycloak.representations.idm.ClientPolicyExecutorConfigurationRepresentation;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyContext;
|
||||
|
|
@ -86,38 +89,40 @@ public class SecureClientUrisExecutor implements ClientPolicyExecutorProvider<Cl
|
|||
confirmSecureRedirectUri(((AuthorizationRequestContext)context).getRedirectUri());
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void confirmSecureUris(ClientRepresentation clientRep) throws ClientPolicyException {
|
||||
// rootUrl
|
||||
String rootUrl = clientRep.getRootUrl();
|
||||
if (rootUrl != null) confirmSecureUris(Arrays.asList(rootUrl), "rootUrl");
|
||||
if (rootUrl != null) confirmSecureUris(List.of(rootUrl), "rootUrl");
|
||||
|
||||
// adminUrl
|
||||
String adminUrl = clientRep.getAdminUrl();
|
||||
if (adminUrl != null) confirmSecureUris(Arrays.asList(adminUrl), "adminUrl");
|
||||
if (adminUrl != null) confirmSecureUris(List.of(adminUrl), "adminUrl");
|
||||
|
||||
// baseUrl
|
||||
String baseUrl = clientRep.getBaseUrl();
|
||||
if (baseUrl != null) confirmSecureUris(Arrays.asList(baseUrl), "baseUrl");
|
||||
|
||||
// web origins
|
||||
List<String> webOrigins = clientRep.getWebOrigins();
|
||||
if (webOrigins != null) confirmSecureUris(webOrigins, "webOrigins");
|
||||
if (baseUrl != null) confirmSecureUris(List.of(baseUrl), "baseUrl");
|
||||
|
||||
// backchannel logout URL
|
||||
String logoutUrl = Optional.ofNullable(clientRep.getAttributes()).orElse(Collections.emptyMap()).get(OIDCConfigAttributes.BACKCHANNEL_LOGOUT_URL);
|
||||
if (logoutUrl != null) confirmSecureUris(Arrays.asList(logoutUrl), "logoutUrl");
|
||||
if (logoutUrl != null) confirmSecureUris(List.of(logoutUrl), "logoutUrl");
|
||||
|
||||
// OAuth2 : redirectUris
|
||||
List<String> redirectUris = clientRep.getRedirectUris();
|
||||
if (redirectUris != null) confirmSecureUris(redirectUris, "redirectUris");
|
||||
|
||||
// web origins
|
||||
List<String> webOrigins = clientRep.getWebOrigins();
|
||||
if (webOrigins != null) {
|
||||
List<String> resolvedWebOriginUrls = resolveUrlWithRedirects(webOrigins, redirectUris, rootUrl, true);
|
||||
confirmSecureUris(resolvedWebOriginUrls, "webOrigins");
|
||||
}
|
||||
|
||||
// OAuth2 : jwks_uri
|
||||
String jwksUri = Optional.ofNullable(clientRep.getAttributes()).orElse(Collections.emptyMap()).get(OIDCConfigAttributes.JWKS_URL);
|
||||
if (jwksUri != null) confirmSecureUris(Arrays.asList(jwksUri), "jwksUri");
|
||||
if (jwksUri != null) confirmSecureUris(List.of(jwksUri), "jwksUri");
|
||||
|
||||
// OIDD : requestUris
|
||||
List<String> requestUris = getAttributeMultivalued(clientRep, OIDCConfigAttributes.REQUEST_URIS);
|
||||
|
|
@ -125,7 +130,27 @@ public class SecureClientUrisExecutor implements ClientPolicyExecutorProvider<Cl
|
|||
|
||||
// CIBA : client notification endpoint
|
||||
String clientNotificationEndpoint = Optional.ofNullable(clientRep.getAttributes()).orElse(Collections.emptyMap()).get(CibaConfig.CIBA_BACKCHANNEL_CLIENT_NOTIFICATION_ENDPOINT);
|
||||
if (clientNotificationEndpoint != null) confirmSecureUris(Arrays.asList(clientNotificationEndpoint), "cibaClientNotificationEndpoint");
|
||||
if (clientNotificationEndpoint != null) confirmSecureUris(List.of(clientNotificationEndpoint), "cibaClientNotificationEndpoint");
|
||||
|
||||
// OIDC: Post Logout URL
|
||||
List<String> postLogoutRedirectUris = getAttributeMultivalued(clientRep, OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS);
|
||||
if (postLogoutRedirectUris != null && !postLogoutRedirectUris.isEmpty()) {
|
||||
List<String> validRedirects = clientRep.getRedirectUris() != null ? clientRep.getRedirectUris() : Collections.emptyList();
|
||||
List<String> resolvedPostLogoutUrls = resolveUrlWithRedirects(postLogoutRedirectUris, validRedirects, clientRep.getRootUrl(), false);
|
||||
confirmSecureUris(resolvedPostLogoutUrls, "postLogoutUris");
|
||||
}
|
||||
|
||||
// logoUri
|
||||
String logoUri = Optional.ofNullable(clientRep.getAttributes()).orElse(Collections.emptyMap()).get(OIDCConfigAttributes.LOGO_URI);
|
||||
if (logoUri != null) confirmSecureUris(List.of(logoUri), "logoUri");
|
||||
|
||||
// termsOfServiceUri
|
||||
String termsOfServiceUri = Optional.ofNullable(clientRep.getAttributes()).orElse(Collections.emptyMap()).get(OIDCConfigAttributes.TOS_URI);
|
||||
if (termsOfServiceUri != null) confirmSecureUris(List.of(termsOfServiceUri), "tosUri");
|
||||
|
||||
// policyUri
|
||||
String policyUri = Optional.ofNullable(clientRep.getAttributes()).orElse(Collections.emptyMap()).get(OIDCConfigAttributes.POLICY_URI);
|
||||
if (policyUri != null) confirmSecureUris(List.of(policyUri), "policyUri");
|
||||
}
|
||||
|
||||
private List<String> getAttributeMultivalued(ClientRepresentation clientRep, String attrKey) {
|
||||
|
|
@ -140,9 +165,11 @@ public class SecureClientUrisExecutor implements ClientPolicyExecutorProvider<Cl
|
|||
}
|
||||
|
||||
for (String uri : uris) {
|
||||
logger.tracev("{0} = {1}", uriType, uri);
|
||||
if (!uri.startsWith("https://") || uri.contains("*")) {
|
||||
throw new ClientPolicyException(OAuthErrorException.INVALID_CLIENT_METADATA, "Invalid " + uriType);
|
||||
if (!uri.isEmpty()) {
|
||||
logger.tracev("{0} = {1}", uriType, uri);
|
||||
if (!uri.startsWith("https://") || uri.contains("*")) {
|
||||
throw new ClientPolicyException(OAuthErrorException.INVALID_CLIENT_METADATA, "Invalid " + uriType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,6 +183,14 @@ public class SecureClientUrisExecutor implements ClientPolicyExecutorProvider<Cl
|
|||
if (!redirectUri.startsWith("https://") || redirectUri.contains("*")) {
|
||||
throw new ClientPolicyException(OAuthErrorException.INVALID_REQUEST, "Invalid redirect_uri");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> resolveUrlWithRedirects(List<String> originalUrls, List<String> redirectUris,
|
||||
String rootUrl, boolean returnAsOrigins) {
|
||||
if (originalUrls == null || originalUrls.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<String> resolvedUrls = RedirectUtils.resolveUrlsWithRedirects(session, originalUrls, rootUrl, redirectUris, returnAsOrigins);
|
||||
return new ArrayList<>(resolvedUrls);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,8 +197,8 @@ public class RealmManager {
|
|||
String baseUrl = "/admin/" + Encode.encodePathAsIs(realm.getName()) + "/console/";
|
||||
adminConsole.setBaseUrl(baseUrl);
|
||||
adminConsole.addRedirectUri(baseUrl + "*");
|
||||
adminConsole.setAttribute(OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS, "+");
|
||||
adminConsole.setWebOrigins(Collections.singleton("+"));
|
||||
adminConsole.setAttribute(OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS, Constants.INCLUDE_REDIRECTS);
|
||||
adminConsole.setWebOrigins(Collections.singleton(Constants.INCLUDE_REDIRECTS));
|
||||
|
||||
adminConsole.setEnabled(true);
|
||||
adminConsole.setAlwaysDisplayInConsole(false);
|
||||
|
|
|
|||
|
|
@ -1216,14 +1216,14 @@ public class ClientPoliciesExecutorTest extends AbstractClientPoliciesTest {
|
|||
clientRep.setAdminUrl("https://client.example.com/admin/");
|
||||
// baseUrl
|
||||
clientRep.setBaseUrl("https://client.example.com/base/");
|
||||
// OAuth2 : redirectUris
|
||||
clientRep.setRedirectUris(Arrays.asList("https://client.example.com/redirect/", "https://client.example.com/callback/"));
|
||||
// web origins
|
||||
clientRep.setWebOrigins(Arrays.asList("https://valid.other.client.example.com/", "https://valid.another.client.example.com/"));
|
||||
// backchannel logout URL
|
||||
Map<String, String> attributes = Optional.ofNullable(clientRep.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put(OIDCConfigAttributes.BACKCHANNEL_LOGOUT_URL, "https://client.example.com/logout/");
|
||||
clientRep.setAttributes(attributes);
|
||||
// OAuth2 : redirectUris
|
||||
clientRep.setRedirectUris(Arrays.asList("https://client.example.com/redirect/", "https://client.example.com/callback/"));
|
||||
// OAuth2 : jwks_uri
|
||||
attributes.put(OIDCConfigAttributes.JWKS_URL, "https://client.example.com/jwks/");
|
||||
clientRep.setAttributes(attributes);
|
||||
|
|
@ -1341,6 +1341,45 @@ public class ClientPoliciesExecutorTest extends AbstractClientPoliciesTest {
|
|||
assertEquals(OAuthErrorException.INVALID_CLIENT_METADATA, e.getError());
|
||||
assertEquals("Invalid cibaClientNotificationEndpoint", e.getErrorDetail());
|
||||
}
|
||||
|
||||
try {
|
||||
updateClientByAdmin(cid, (ClientRepresentation clientRep) -> {
|
||||
// OIDC: logo_uri
|
||||
Map<String, String> attributes = Optional.ofNullable(clientRep.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put("logoUri", "http://client.example.com/logo/");
|
||||
clientRep.setAttributes(attributes);
|
||||
});
|
||||
fail();
|
||||
} catch (ClientPolicyException e) {
|
||||
assertEquals(OAuthErrorException.INVALID_CLIENT_METADATA, e.getError());
|
||||
assertEquals("Invalid logoUri", e.getErrorDetail());
|
||||
}
|
||||
|
||||
try {
|
||||
updateClientByAdmin(cid, (ClientRepresentation clientRep) -> {
|
||||
// OIDC: tos_uri (Terms of Service)
|
||||
Map<String, String> attributes = Optional.ofNullable(clientRep.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put("tosUri", "http://client.example.com/tos/");
|
||||
clientRep.setAttributes(attributes);
|
||||
});
|
||||
fail();
|
||||
} catch (ClientPolicyException e) {
|
||||
assertEquals(OAuthErrorException.INVALID_CLIENT_METADATA, e.getError());
|
||||
assertEquals("Invalid tosUri", e.getErrorDetail());
|
||||
}
|
||||
|
||||
try {
|
||||
updateClientByAdmin(cid, (ClientRepresentation clientRep) -> {
|
||||
// OIDC: policy_uri
|
||||
Map<String, String> attributes = Optional.ofNullable(clientRep.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put("policyUri", "http://client.example.com/policy/");
|
||||
clientRep.setAttributes(attributes);
|
||||
});
|
||||
fail();
|
||||
} catch (ClientPolicyException e) {
|
||||
assertEquals(OAuthErrorException.INVALID_CLIENT_METADATA, e.getError());
|
||||
assertEquals("Invalid policyUri", e.getErrorDetail());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1830,4 +1869,133 @@ public class ClientPoliciesExecutorTest extends AbstractClientPoliciesTest {
|
|||
return client.execute(post);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecureClientRegisteringUriEnforceExecutorWithRedirectWildcard() throws Exception {
|
||||
// register profiles
|
||||
String json = (new ClientProfilesBuilder()).addProfile(
|
||||
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Ensimmainen Profiili")
|
||||
.addExecutor(SecureClientUrisExecutorFactory.PROVIDER_ID, null)
|
||||
.toRepresentation()
|
||||
).toString();
|
||||
updateProfiles(json);
|
||||
|
||||
// register policies
|
||||
json = (new ClientPoliciesBuilder()).addPolicy(
|
||||
(new ClientPolicyBuilder()).createPolicy(POLICY_NAME, "Ensimmainen Politiikka", Boolean.TRUE)
|
||||
.addCondition(ClientUpdaterContextConditionFactory.PROVIDER_ID,
|
||||
createClientUpdateContextConditionConfig(Arrays.asList(
|
||||
ClientUpdaterContextConditionFactory.BY_AUTHENTICATED_USER,
|
||||
ClientUpdaterContextConditionFactory.BY_INITIAL_ACCESS_TOKEN,
|
||||
ClientUpdaterContextConditionFactory.BY_REGISTRATION_ACCESS_TOKEN)))
|
||||
.addProfile(PROFILE_NAME)
|
||||
.toRepresentation()
|
||||
).toString();
|
||||
updatePolicies(json);
|
||||
|
||||
|
||||
String cid = null;
|
||||
String clientId = generateSuffixedName(CLIENT_NAME);
|
||||
try {
|
||||
cid = createClientByAdmin(clientId, (ClientRepresentation clientRep) -> {
|
||||
clientRep.setServiceAccountsEnabled(Boolean.TRUE);
|
||||
clientRep.setRedirectUris(List.of("https://client.example.com/redirect/"));
|
||||
});
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
|
||||
try { // Redirect relative wildcard - '+' as single value
|
||||
updateClientByAdmin(cid, (ClientRepresentation clientRep) -> {
|
||||
// rootUrl
|
||||
clientRep.setRootUrl("https://client.example.com/");
|
||||
// adminUrl
|
||||
clientRep.setAdminUrl("https://client.example.com/admin/");
|
||||
// baseUrl
|
||||
clientRep.setBaseUrl("https://client.example.com/base/");
|
||||
// OAuth2 : redirectUris
|
||||
clientRep.setRedirectUris(Arrays.asList("https://client.example.com/redirect/", "https://client.example.com/callback/"));
|
||||
// web origins
|
||||
clientRep.setWebOrigins(List.of("+"));
|
||||
// backchannel logout URL
|
||||
Map<String, String> attributes = Optional.ofNullable(clientRep.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put(OIDCConfigAttributes.BACKCHANNEL_LOGOUT_URL, "https://client.example.com/logout/");
|
||||
clientRep.setAttributes(attributes);
|
||||
// OIDC: postLogoutUris
|
||||
setAttributeMultivalued(clientRep, OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS, List.of("+"));
|
||||
// OAuth2 : jwks_uri
|
||||
attributes.put(OIDCConfigAttributes.JWKS_URL, "https://client.example.com/jwks/");
|
||||
clientRep.setAttributes(attributes);
|
||||
// OIDC : requestUris
|
||||
setAttributeMultivalued(clientRep, OIDCConfigAttributes.REQUEST_URIS, Arrays.asList("https://client.example.com/request/", "https://client.example.com/reqobj/"));
|
||||
// CIBA Client Notification Endpoint
|
||||
attributes.put(CibaConfig.CIBA_BACKCHANNEL_CLIENT_NOTIFICATION_ENDPOINT, "https://client.example.com/client-notification/");
|
||||
clientRep.setAttributes(attributes);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
|
||||
try { // Redirect relative wildcard - '+' with multiple values
|
||||
updateClientByAdmin(cid, (ClientRepresentation clientRep) -> {
|
||||
// rootUrl
|
||||
clientRep.setRootUrl("https://client.example.com/");
|
||||
// adminUrl
|
||||
clientRep.setAdminUrl("https://client.example.com/admin/");
|
||||
// baseUrl
|
||||
clientRep.setBaseUrl("https://client.example.com/base/");
|
||||
// OAuth2 : redirectUris
|
||||
clientRep.setRedirectUris(List.of("https://client.example.com/redirect/"));
|
||||
// web origins
|
||||
clientRep.setWebOrigins(Arrays.asList("https://valid.other.client.example.com/", "https://valid.another.client.example.com/", "+"));
|
||||
// backchannel logout URL
|
||||
Map<String, String> attributes = Optional.ofNullable(clientRep.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put(OIDCConfigAttributes.BACKCHANNEL_LOGOUT_URL, "https://client.example.com/logout/");
|
||||
clientRep.setAttributes(attributes);
|
||||
// OIDC: postLogoutUris
|
||||
setAttributeMultivalued(clientRep, OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS, Arrays.asList("https://client.example.com/postlogout/", "+"));
|
||||
// OAuth2 : jwks_uri
|
||||
attributes.put(OIDCConfigAttributes.JWKS_URL, "https://client.example.com/jwks/");
|
||||
clientRep.setAttributes(attributes);
|
||||
// OIDC : requestUris
|
||||
setAttributeMultivalued(clientRep, OIDCConfigAttributes.REQUEST_URIS, Arrays.asList("https://client.example.com/request/", "https://client.example.com/reqobj/"));
|
||||
// CIBA Client Notification Endpoint
|
||||
attributes.put(CibaConfig.CIBA_BACKCHANNEL_CLIENT_NOTIFICATION_ENDPOINT, "https://client.example.com/client-notification/");
|
||||
clientRep.setAttributes(attributes);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
|
||||
try { // Redirect relative wildcard - '+' with no redirect value added
|
||||
updateClientByAdmin(cid, (ClientRepresentation clientRep) -> {
|
||||
// rootUrl
|
||||
clientRep.setRootUrl("https://client.example.com/");
|
||||
// adminUrl
|
||||
clientRep.setAdminUrl("https://client.example.com/admin/");
|
||||
// baseUrl
|
||||
clientRep.setBaseUrl("https://client.example.com/base/");
|
||||
// OAuth2 : redirectUris
|
||||
clientRep.setRedirectUris(null);
|
||||
// web origins
|
||||
clientRep.setWebOrigins(Arrays.asList("+", "https://valid.other.client.example.com/"));
|
||||
// backchannel logout URL
|
||||
Map<String, String> attributes = Optional.ofNullable(clientRep.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put(OIDCConfigAttributes.BACKCHANNEL_LOGOUT_URL, "https://client.example.com/logout/");
|
||||
clientRep.setAttributes(attributes);
|
||||
// OIDC: postLogoutUris
|
||||
setAttributeMultivalued(clientRep, OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS, Arrays.asList("https://client.example.com/postlogout/", "+"));
|
||||
// OAuth2 : jwks_uri
|
||||
attributes.put(OIDCConfigAttributes.JWKS_URL, "https://client.example.com/jwks/");
|
||||
clientRep.setAttributes(attributes);
|
||||
// OIDC : requestUris
|
||||
setAttributeMultivalued(clientRep, OIDCConfigAttributes.REQUEST_URIS, Arrays.asList("https://client.example.com/request/", "https://client.example.com/reqobj/"));
|
||||
// CIBA Client Notification Endpoint
|
||||
attributes.put(CibaConfig.CIBA_BACKCHANNEL_CLIENT_NOTIFICATION_ENDPOINT, "https://client.example.com/client-notification/");
|
||||
clientRep.setAttributes(attributes);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue