apereo/cas · error · IllegalArgumentException
Invalid sector identifier uri
Error message
Invalid sector identifier uri
What it means
When the registration request supplies a sector_identifier_uri, the translator fetches it and expects the document to be a JSON array of redirect URIs exactly equal to the request's redirect_uris. If the fetched list differs, translate() throws this IllegalArgumentException per the OIDC dynamic registration spec.
Solutions
- Update the sector_identifier_uri document so its JSON array exactly equals the redirect_uris sent in the registration request (same values, same order)
- If redirect URIs differ across clients, host a per-client sector identifier document or omit sector_identifier_uri
- Check for trailing-slash or http vs https differences between the document and request URIs
Example fix
// before (sector document) ["https://app.example.com/other-callback"] // after (must match request redirect_uris) ["https://app.example.com/callback"]
Defensive patterns
Strategy: validation
Validate before calling
List<String> sectorUrls = fetchSectorIdentifierUri(sectorUri);
if (!sectorUrls.equals(request.getRedirectUris())) {
throw new IllegalStateException("sector_identifier_uri document must equal redirect_uris");
} Try / catch
try { translator.translate(request); } catch (IllegalArgumentException e) { if (e.getMessage().contains("sector identifier")) { /* reconcile sector document with redirect_uris */ } else throw e; } Prevention
- Regenerate the sector identifier document whenever redirect URIs change
- Keep element order identical between document and request
- Host one sector document per client group only when URI sets are identical
When it happens
Trigger: translate() -> validate(): a sector_identifier_uri is provided, the remote document returns HTTP 200 and parses as a JSON array of strings, but that array does not exactly match (order-sensitive) registrationRequest.getRedirectUris().
Common situations: The sector identifier document is shared across several clients with different redirect URI sets, the document is stale after the client changed redirect URIs, or list ordering differs between the document and the request.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Redirect URI cannot contain a fragment
- Invalid logo uri from an unknown host
- Invalid policy uri from an unknown host
- 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/ac52f1a7c269006d.
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:276
private void validate(final OidcClientRegistrationRequest registrationRequest,
final OidcRegisteredService registeredService) throws Exception {
val context = configurationContext.getObject();
if (StringUtils.isNotBlank(registeredService.getSectorIdentifierUri())) {
HttpResponse sectorResponse = null;
try {
val exec = HttpExecutionRequest
.builder()
.method(HttpMethod.GET)
.url(registeredService.getSectorIdentifierUri())
.build();
sectorResponse = HttpUtils.execute(exec);
if (sectorResponse != null && sectorResponse.getCode() == HttpStatus.SC_OK) {
try (val content = ((HttpEntityContainer) sectorResponse).getEntity().getContent()) {
val result = IOUtils.toString(content, StandardCharsets.UTF_8);
val expectedType = MAPPER.getTypeFactory().constructParametricType(List.class, String.class);
val urls = MAPPER.readValue(JsonValue.readHjson(result).toString(), expectedType);
if (!urls.equals(registrationRequest.getRedirectUris())) {
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");View on GitHub (pinned to e7288fc434)