{"record":{"id":"1cae078605c5f3a4","repo":"apereo/cas","slug":"unknown-realm","errorCode":null,"errorMessage":"Unknown realm: ","messagePattern":"Unknown realm: ","errorType":"exception","errorClass":"STSException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-ws-sts-api/src/main/java/org/apereo/cas/support/realm/UriRealmParser.java","lineNumber":36,"sourceCode":"@Slf4j\n@RequiredArgsConstructor\npublic class UriRealmParser implements RealmParser {\n\n    private final Map<String, RealmProperties> realmMap;\n\n    @Override\n    public String parseRealm(final Map<String, Object> messageContext) throws STSException {\n        val url = (String) messageContext.get(\"org.apache.cxf.request.url\");\n        val st = new StringTokenizer(url, \"/\");\n        var count = st.countTokens();\n        if (count <= 1) {\n            return null;\n        }\n        count--;\n        val realm = getRealm(st, count);\n        if (StringUtils.isBlank(realm) || !realmMap.containsKey(realm)) {\n            LOGGER.warn(\"Unknown realm: [{}]\", realm);\n            throw new STSException(\"Unknown realm: \" + realm);\n        }\n\n        LOGGER.debug(\"URI realm parsed: [{}]\", realm);\n        return realm.trim();\n    }\n\n    private static String getRealm(final StringTokenizer st, final int count) {\n        var realm = StringUtils.EMPTY;\n        for (var i = 0; i < count; i++) {\n            realm = st.nextToken();\n        }\n        return realm.toUpperCase(Locale.ENGLISH);\n    }\n}\n\n","sourceCodeStart":18,"sourceCodeEnd":52,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-ws-sts-api/src/main/java/org/apereo/cas/support/realm/UriRealmParser.java#L18-L52","documentation":"UriRealmParser.parseRealm derives a realm from the WS-Trust request's `appliesTo` URI (e.g. http://schemas.xmlsoap.org/ws/2005/identity/org/apereo/cas) and looks it up in a configured realm map. If the parsed realm is blank or not present in the map, it throws STSException(\"Unknown realm: \" + realm), refusing to issue a security token for an unconfigured realm.","triggerScenarios":"A WS-Trust RST is submitted to the STS whose AppliesTo URI, after parsing via getRealm (segment at the adjusted token count), yields a realm string that is blank or absent from the `realmMap` configured on this realm parser.","commonSituations":"STS security configuration (cas.authn.ws-idp / STS realm settings) missing an entry for the RP's realm; RP sending a wrong or truncated appliesTo URI; CASConfigurationProperties realm map keys differing in case or trailing slash from the parsed value; token counts in the URI differing from the parser's expectations.","solutions":["Add the missing realm to the configured realm map (STS realm configuration) so the parsed appliesTo value matches a known key exactly.","Log the appliesTo URI from the failing RST and compare it with configured realm keys for case/slash/spelling mismatches.","Correct the RP/client to send the canonical AppliesTo URI that the CAS STS realm configuration expects.","If realms are dynamic, supply a custom RealmParser bean whose map covers the additional realms instead of UriRealmParser's static map."],"exampleFix":"// before: no entry for requested realm\nmap.put(\"https://cas.example.org/ws/sts/realm1\", \"encryption-key\");\n// after: add the realm the RP's appliesTo URI resolves to\nmap.put(\"https://cas.example.org/ws/sts/realm1\", \"encryption-key\");\nmap.put(\"https://cas.example.org/ws/sts/realm2\", \"encryption-key-2\");","handlingStrategy":"validation","validationCode":"// Client-side pre-check before calling the STS:\nString appliesTo = \"https://cas.example.org/ws/sts/realm2\";\nif (!configuredRealmKeys.contains(appliesTo)) {\n    throw new IllegalArgumentException(\"AppliesTo realm not configured in CAS STS: \" + appliesTo);\n}","typeGuard":null,"tryCatchPattern":"// Server-side, wrapping STS token issuance:\ntry {\n    SecurityToken token = sts.issueToken(rst);\n} catch (STSException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unknown realm\")) {\n        throw new ConfigurationException(\"Realm not configured: \" + e.getMessage());\n    }\n    throw e;\n}","preventionTips":["Keep the realm map keys byte-identical (case, slashes, trailing segments) to the AppliesTo URIs RPs actually send.","Add every new RP's realm to the STS configuration before onboarding it.","Log parsed realm values at debug level to catch mismatches early."],"tags":["ws-trust","sts","configuration"],"backgroundTag":"resource-not-found","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}