apereo/cas · error · IllegalArgumentException
Invalid logo uri from an unknown host
Error message
Invalid logo uri from an unknown host
What it means
The translator restricts the client's logo_uri to hosts already present in the request's redirect URIs, preventing a client from pointing its logo at an arbitrary host. If the logo URI's host is not among the redirect URI hosts, translate() -> validate() throws this IllegalArgumentException.
Solutions
- Host the logo on the same host as one of the redirect URis, or add that host to the redirect_uris
- Register the client without a logo and attach it via service management afterward if allowed
- Normalize the logo URI (correct scheme/host) so its host matches a redirect URI host
Example fix
// before "redirect_uris": ["https://app.example.com/callback"], "logo_uri": "https://cdn.example.net/logo.png" // after "redirect_uris": ["https://app.example.com/callback"], "logo_uri": "https://app.example.com/logo.png"
Defensive patterns
Strategy: validation
Validate before calling
Set<String> hosts = request.getRedirectUris().stream()
.map(u -> URI.create(u).getHost()).collect(Collectors.toSet());
if (request.getLogo() != null && !hosts.contains(URI.create(request.getLogo()).getHost())) {
throw new IllegalArgumentException("logo_uri host must match a redirect_uri host");
} Try / catch
try { translator.translate(request); } catch (IllegalArgumentException e) { if (e.getMessage().contains("logo uri")) { /* fix logo_uri host */ } else throw e; } Prevention
- Serve client metadata assets (logo, policy) from the same host as redirect URIs
- Avoid CDN or third-party hosts for logo_uri in dynamic registration
- Validate URI hosts before submitting the registration request
When it happens
Trigger: translate() -> validate(): registrationRequest.getLogo() is non-blank and new URI(logo).getHost() is not contained in the set of hosts extracted from redirect_uris.
Common situations: Hosting the logo on a CDN (e.g. cdn.example.com) while redirect URIs point at app.example.com; using a placeholder or external image URL like a logo from a public icon service; protocol-relative or typo'd hosts.
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 policy 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/d9884253f80e2c8c.
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:294
throw new IllegalArgumentException("Invalid sector identifier uri");
}
}
}
} finally {
HttpUtils.close(sectorResponse);
}
}
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)