apereo/cas · error · IllegalArgumentException
Invalid policy uri from an unknown host
Error message
Invalid policy uri from an unknown host
What it means
Like the logo check, the translator requires the policy_uri host to appear among the redirect URI hosts. A policy document served from any other host is rejected with this IllegalArgumentException during dynamic client registration.
Solutions
- Serve the policy document from the same host as one of the redirect URIs
- Add the policy host to redirect_uris (only if genuinely a valid redirect target)
- Omit policy_uri from the registration request and configure it later via service management
Example fix
// before "redirect_uris": ["https://app.example.com/callback"], "policy_uri": "https://legal.example.org/privacy" // after "redirect_uris": ["https://app.example.com/callback"], "policy_uri": "https://app.example.com/privacy"
Defensive patterns
Strategy: validation
Validate before calling
Set<String> hosts = request.getRedirectUris().stream()
.map(u -> URI.create(u).getHost()).collect(Collectors.toSet());
if (request.getPolicyUri() != null && !hosts.contains(URI.create(request.getPolicyUri()).getHost())) {
throw new IllegalArgumentException("policy_uri host must match a redirect_uri host");
} Try / catch
try { translator.translate(request); } catch (IllegalArgumentException e) { if (e.getMessage().contains("policy uri")) { /* fix policy_uri host */ } else throw e; } Prevention
- Host policy documents on the application's own domain
- Omit policy_uri when no same-host document exists
- Check hosts of all client metadata URIs in one validation pass
When it happens
Trigger: translate() -> validate(): registrationRequest.getPolicyUri() is non-blank and new URI(policyUri).getHost() is not in the hosts derived from redirect_uris.
Common situations: Pointing policy_uri at a separate corporate/legal site (e.g. policies.example.org) while the app lives on app.example.com; leaving a template or example policy URL in the registration request.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- Invalid logo uri from an unknown host
- Redirect URI cannot contain a fragment
- Invalid sector identifier uri
- Missing required principal attribute for claim
- Invalid OIDC pushed authorization request at
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/9b6a41e65811e414.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/dynareg/OidcDefaultClientRegistrationRequestTranslator.java:301
}
val oidc = context.getCasProperties().getAuthn().getOidc();
if (!oidc.getRegistration().getDynamicClientRegistrationMode().isProtected()
&& (StringUtils.isNotBlank(registrationRequest.getPolicyUri()) || StringUtils.isNotBlank(registrationRequest.getLogo()))) {
val hosts = registrationRequest.getRedirectUris()
.stream()
.map(uri -> FunctionUtils.doUnchecked(() -> new URI(uri).getHost())).toList();
if (StringUtils.isNotBlank(registrationRequest.getLogo())) {
val logo = new URI(registrationRequest.getLogo()).getHost();
if (!hosts.contains(logo)) {
throw new IllegalArgumentException("Invalid logo uri from an unknown host");
}
}
if (StringUtils.isNotBlank(registrationRequest.getPolicyUri())) {
val policy = new URI(registrationRequest.getPolicyUri()).getHost();
if (!hosts.contains(policy)) {
throw new IllegalArgumentException("Invalid policy uri from an unknown host");
}
}
}
if (Strings.CI.equalsAny(registeredService.getBackchannelTokenDeliveryMode(),
OidcBackchannelTokenDeliveryModes.PUSH.getMode(), OidcBackchannelTokenDeliveryModes.PING.getMode())) {
Assert.hasText(registeredService.getBackchannelClientNotificationEndpoint(),
"Backchannel client notification endpoint must be specified");
Assert.isTrue(Strings.CI.startsWith(registeredService.getBackchannelClientNotificationEndpoint(), "https://"),
"Backchannel client notification endpoint MUST be an HTTPS url");
}
}
}
View on GitHub (pinned to e7288fc434)