ory / ory/sdk

PHP library: Permission check with subject_set is not working

Open
#442 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
PHP
Stars
178
Forks
96
Avg merge
6d 23h
Merged PRs (30d)
3

Description

Preflight checklist
Ory Network Project

No response

Describe the bug

Many function calls have subjectSet variable, but if it's empty string, it is removed from the request causing error. Create Relationship does not have this problem because subjectSet is given as array where get/delete relationships/check permission do not.

So creating works:

$relationshipApi->createRelationship([
                'namespace' => 'Plan',
                'object' => $planId,
                'relation' => 'features',
                'subject_set' => [
                    'namespace' => 'Feature',
                    'object' => $featureId,
                ],
            ]);

But this does not:

$permResult = Ory::permission()->checkPermission(
          'Plan',
            $planId,
            'includes_feature',
            null,
            'Feature',
            $featureCheckId,
            '', // this is the problem, empty string
        );

PHP ory/client library is not working correctly with the check permissions call when using subject_set.realation value "" (emtpy string) the ObjectSerializer thinks it is not required and removes it because it's empty value.

Testing by modifiying the PermissionAPI class line 935-942 to this:

        $queryParams = array_merge($queryParams, ObjectSerializer::toQueryValue(
            $subjectSetRelation,
            'subject_set.relation', // param base name
            'string', // openApiType
            'form', // style
            true, // explode
            (empty($subjectSetObject) ? false : true) // required
        ) ?? []);

and then it works. ALso same change for the getRelationship and deleteRelationship...

Reproducing the bug
$permResult = Ory::permission()->checkPermission(
          'Plan',
            $planId,
            'includes_feature',
            null,
            'Feature',
            $featureCheckId,
            '', // this is the problem, empty string
        );

Causes error because subject_set.relation needs to be empty but because it is empty, it is not included in the request causing this error:

[400] Client error: `GET http://keto:4466/relation-tuples/check/openapi?namespace=Plan&object=planId&relation=includes_feature&subject_set.namespace=Feature&subject_set.object=featId` resulted in a `400 Bad Request` response:{"error":{"code":400,"status":"Bad Request","message":"incomplete subject, provide \"subject_id\" or a complete \"subjec (truncated...)

And keto log:

keto-1  | time=2025-07-30T23:44:02Z level=info msg=completed handling request http_request=map[headers:map[accept:application/json content-type:application/json user-agent:OpenAPI-Generator/1.0.0/PHP] host:keto:4466 method:GET path:/relation-tuples/check/openapi query:namespace=Plan&object=planId&relation=includes_feature&subject_set.namespace=Feature&subject_set.object=featId remote:172.19.0.37:50472 scheme:http] http_response=map[headers:map[content-type:application/json] size:133 status:400 text_status:Bad Request took:86.667µs]

As you can see, the subject_set.relation is missing from the request even though it was defined in the code.

When trying to do the same request with curl with the empty string subject_set.releation:

# curl -s "http://localhost:4466/relation-tuples/check/openapi" \
>   -G \
>   --data-urlencode "namespace=Plan" \
>   --data-urlencode "object=planId" \
>   --data-urlencode "relation=includes_feature" \
>   --data-urlencode "subject_set.namespace=Feature" \
>   --data-urlencode "subject_set.object=featId" \
>   --data-urlencode "subject_set.relation="
{"allowed":true}

It works, but when doing without it like the PHP -library:

# curl -s "http://localhost:4466/relation-tuples/check/openapi" \
>    -G \
>    --data-urlencode "namespace=Plan" \
>    --data-urlencode "object=planId" \
>    --data-urlencode "relation=includes_feature" \
>    --data-urlencode "subject_set.namespace=Feature" \
>    --data-urlencode "subject_set.object=featId" 
{"error":{"code":400,"status":"Bad Request","message":"incomplete subject, provide \"subject_id\" or a complete \"subject_set.*\""}}

It does not work, just like the PHP ory/client library because the empty string relation is missing.

Relevant log output

Relevant configuration

Version

Ory keto 0.14.0 - Ory client php-library ory/client v1.21.3

On which operating system are you observing this issue?

None

In which environment are you deploying?

Docker Compose

Additional Context

I made the bug report first to here: https://github.com/ory/client-php/issues/2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the generated PermissionAPI class around lines 935-942 and inspect ObjectSerializer::toQueryValue, comparing the working createRelationship parameters with checkPermission. Trace the corresponding getRelationship and deleteRelationship paths. Done means empty subject_set.relation is retained in each request and the reported check-permission reproduction succeeds.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.