{"record":{"id":"ad86d713db1b6d14","repo":"apereo/cas","slug":"resource-set-owner-does-not-match-the-authenticate","errorCode":null,"errorMessage":"Resource-set owner does not match the authenticated profile","messagePattern":"Resource-set owner does not match the authenticated profile","errorType":"validation","errorClass":"InvalidResourceSetException","httpStatus":403,"severity":"error","filePath":"support/cas-server-support-oauth-uma-core/src/main/java/org/apereo/cas/uma/ticket/resource/ResourceSet.java","lineNumber":80,"sourceCode":"    private Set<ResourceSetPolicy> policies = new HashSet<>();\n\n    /**\n     * Validate.\n     *\n     * @param profile the profile\n     */\n    @JsonIgnore\n    public void validate(final UserProfile profile) {\n        if (StringUtils.isBlank(getClientId())) {\n            throw new InvalidResourceSetException(HttpStatus.BAD_REQUEST.value(), \"Authentication request does contain a client id\");\n        }\n\n        if (getScopes().isEmpty()) {\n            throw new InvalidResourceSetException(HttpStatus.BAD_REQUEST.value(), \"Resource set registration is missing scopes\");\n        }\n\n        if (!getOwner().equals(profile.getId())) {\n            throw new InvalidResourceSetException(HttpStatus.FORBIDDEN.value(), \"Resource-set owner does not match the authenticated profile\");\n        }\n    }\n}\n","sourceCodeStart":62,"sourceCodeEnd":84,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oauth-uma-core/src/main/java/org/apereo/cas/uma/ticket/resource/ResourceSet.java#L62-L84","documentation":"The owner recorded on the UMA resource set must equal the id of the authenticated profile performing validation. A mismatch throws InvalidResourceSetException with HTTP 403, preventing a client or user from registering/managing a resource set owned by someone else.","triggerScenarios":"Registering or validating a resource set whose 'owner' field differs from the authenticated UserProfile.getId() (typically the authenticated client id or subject), in ResourceSet.validate.","commonSituations":"Registering on behalf of another client while authenticated as your own; owner field set to a human username but the profile id is the OAuth client id (or vice versa); stale resource-set templates carrying an old owner; case differences between owner and profile id.","solutions":["Set the resource set's owner to the exact id of the authenticated profile (commonly the clientId for client-registered sets)","Confirm the token used for registration belongs to the same client/user recorded as owner","Check for case/whitespace differences between owner and profile id","Re-register the resource set under the correct authenticated identity rather than spoofing owner"],"exampleFix":"// before\n{\"owner\":\"alice\",\"clientId\":\"myClient\",...}  // authenticated as myClient\n// after\n{\"owner\":\"myClient\",\"clientId\":\"myClient\",...}","handlingStrategy":"validation","validationCode":"if (!Objects.equals(resourceSet.getOwner(), authenticatedProfile.getId())) {\n  throw new SecurityException(\"Owner must match authenticated profile id\");\n}","typeGuard":"boolean ownerMatches(ResourceSet rs, UserProfile p) { return Objects.equals(rs.getOwner(), p.getId()); }","tryCatchPattern":"try { registerResourceSet(rs); } catch (InvalidResourceSetException e) { return ResponseEntity.status(403).body(e.getMessage()); }","preventionTips":["Derive owner from the authenticated profile id, never hardcode it","Authenticate with the same client that owns the resource set","Normalize owner/profile id casing and trim whitespace before comparing"],"tags":["uma","resource-set","ownership","http-403"],"backgroundTag":"permission-denied","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"}