apereo/cas · warning
Service definition [ ] is undefined or it's not an OpenId…
Error message
Service definition [{}] is undefined or it's not an OpenId Connect relying party What it means
PairwiseOidcRegisteredServiceUsernameAttributeProvider.resolveUsernameInternal checks that the registered service is an OidcRegisteredService before generating a pairwise subject identifier. If the service is null or of another type, it logs this warning and falls back to the raw principal id, meaning pairwise (per-sector persistent) subject behavior is silently not applied.
Solutions
- Make sure the service is registered as an OidcRegisteredService (correct @class in the service JSON).
- Remove the pairwise username provider from non-OIDC services; use a suitable provider instead.
- Verify the service registry entry loads correctly (service id/name) so context.getRegisteredService() is not null.
Example fix
// before "@class": "org.apereo.cas.services.RegisteredServiceImpl" // after "@class": "org.apereo.cas.services.OidcRegisteredService"
Defensive patterns
Strategy: type-guard
Validate before calling
if (registeredService == null || !(registeredService instanceof OidcRegisteredService)) {
throw new IllegalArgumentException("Pairwise provider requires an OidcRegisteredService");
} Type guard
boolean isOidcService(RegisteredService svc) {
return svc instanceof OidcRegisteredService;
} Prevention
- Use correct @class in service JSON when enabling pairwise subjects
- Only attach pairwise username providers to OIDC services
- Validate service definitions in the management app before saving
When it happens
Trigger: Assigning the pairwise username attribute provider to a non-OIDC registered service (e.g. a plain OAuth or CAS service), or resolving the username during processing where the service definition failed to load (null context.getRegisteredService()).
Common situations: Copy-pasting a username attribute provider configuration between service types; service registry returning a generic RegisteredService; misconfigured service JSON missing @class OidcRegisteredService.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Service definition [ ] does not request a pairwise subject…
- Denied
- cannot be authorized
- Cannot authorize principal
- UNAUTHORIZED_SERVICE_PROXY
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/d38e7f41ddba012f.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-services/src/main/java/org/apereo/cas/services/PairwiseOidcRegisteredServiceUsernameAttributeProvider.java:53
* @author Misagh Moayyed
* @since 5.2.0
*/
@Slf4j
@Getter
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Setter
public class PairwiseOidcRegisteredServiceUsernameAttributeProvider extends BaseRegisteredServiceUsernameAttributeProvider {
@Serial
private static final long serialVersionUID = 469929103943101717L;
private PersistentIdGenerator persistentIdGenerator = new OidcPairwisePersistentIdGenerator();
@Override
public String resolveUsernameInternal(final RegisteredServiceUsernameProviderContext context) {
if (context.getRegisteredService() == null || !OidcRegisteredService.class.isAssignableFrom(context.getRegisteredService().getClass())) {
LOGGER.warn("Service definition [{}] is undefined or it's not an OpenId Connect relying party", context.getRegisteredService());
return context.getPrincipal().getId();
}
val oidcSvc = (OidcRegisteredService) context.getRegisteredService();
if (StringUtils.isBlank(oidcSvc.getSubjectType())
|| Strings.CI.equals(OidcSubjectTypes.PUBLIC.getType(), oidcSvc.getSubjectType())) {
LOGGER.warn("Service definition [{}] does not request a pairwise subject type", oidcSvc);
return context.getPrincipal().getId();
}
val sectorIdentifier = getSectorIdentifier(oidcSvc);
val id = this.persistentIdGenerator.generate(context.getPrincipal(), sectorIdentifier);
LOGGER.debug("Resolved username [{}] for pairwise access", id);
return id;
}
private static @Nullable String getSectorIdentifier(final OidcRegisteredService client) {
if (StringUtils.isNotBlank(client.getSectorIdentifierUri())) {
val uri = UriComponentsBuilder.fromUriString(client.getSectorIdentifierUri()).build();
return uri.getHost();View on GitHub (pinned to e7288fc434)