ory / sdk

The place where ORY's SDKs are being auto-generated
Apache License 2.0
139 stars 86 forks source link

PHP ory/client:v0.2.0-alpha.60 and hydra 2.0.1, replayed client gets rejected due to serialization issues #224

Open AlbinoDrought opened 1 year ago

AlbinoDrought commented 1 year ago

Preflight checklist

Describe the bug

The PHP version of ory/client:v0.2.0-alpha.60 sends invalid jwks property in the below scenario:

Reproducing the bug

Setup:

use \Ory\Client\Api\V0alpha2Api;
use \Ory\Client\Model\OAuth2Client;

// $api = new V0alpha2Api(...);

// create random client, just for test
$client = $api->adminCreateOAuth2Client(new OAuth2Client());
$id = $client->getClientId();

Reproduce:

// get client from API and then send it back
$client = $api->adminGetOAuth2Client($id);
$api->adminUpdateOAuth2Client($client->getClientId(), $client);

Relevant log output

PHP:

> Ory\Client\ApiException with message '[400] Client error: `PUT http://hydra:4445/admin/clients/e83ab326-7a5b-44ed-a2ea-0aa3ab9eeeaf` resulted in a `400 Bad Request` response:
> {"error":"The request was malformed or contained invalid parameters","error_description":"Unable to decode the request b (truncated...)

Hydra:

> time=2022-11-04T21:00:39Z level=info msg=An error occurred while handling a request audience=application error=map[debug: message:The request was malformed or contained invalid parameters reason:Unable to decode the request body: json: cannot unmarshal array into Go struct field Client.jwks of type x.JoseJSONWebKeySet status:Bad Request status_code:400] http_request=map[headers:map[accept:application/json authorization:Value is sensitive and has been redacted. To see the value set config key "log.leak_sensitive_values = true" or environment variable "LOG_LEAK_SENSITIVE_VALUES=true". content-length:536 content-type:application/json user-agent:OpenAPI-Generator/1.0.0/PHP] host:hydra:4445 method:PUT path:/admin/clients/e83ab326-7a5b-44ed-a2ea-0aa3ab9eeeaf query:<nil> remote:172.27.0.10:59542 scheme:http] http_response=map[status_code:400] service_name=Ory Hydra service_version=v2.0.1
> time=2022-11-04T21:00:39Z level=info msg=completed handling request http_request=map[headers:map[accept:application/json authorization:Value is sensitive and has been redacted. To see the value set config key "log.leak_sensitive_values = true" or environment variable "LOG_LEAK_SENSITIVE_VALUES=true". content-length:536 content-type:application/json user-agent:OpenAPI-Generator/1.0.0/PHP] host:hydra:4445 method:PUT path:/admin/clients/e83ab326-7a5b-44ed-a2ea-0aa3ab9eeeaf query:<nil> remote:172.27.0.10:59542 scheme:http] http_response=map[headers:map[cache-control:private, no-cache, no-store, must-revalidate content-type:application/json] size:217 status:400 text_status:Bad Request took:693.999µs]

Relevant configuration

No response

Version

ory/client:v0.2.0-alpha.60, hydra 2.0.1

On which operating system are you observing this issue?

Linux

In which environment are you deploying?

Docker

Additional Context

Can be worked around with $client->setJwks((object)[]); or $client->setJwks(null);

aeneasr commented 1 year ago

Could you show the payload that gets sent by the client? :) That would be tremendously helpful!

AlbinoDrought commented 1 year ago

Hello,

Here's the payload that gets sent:

PUT http://hydra:4445/admin/clients/af60e02b-f5a2-47c0-ba79-23d1937b8dfd

{"allowed_cors_origins":[],"audience":[],"client_id":"af60e02b-f5a2-47c0-ba79-23d1937b8dfd","client_name":"","client_secret_expires_at":0,"client_uri":"","contacts":[],"created_at":"2022-11-09T01:00:36+00:00","grant_types":[],"jwks":[],"logo_uri":"","metadata":[],"owner":"","policy_uri":"","redirect_uris":[],"response_types":[],"scope":"offline_access offline openid","subject_type":"public","token_endpoint_auth_method":"client_secret_basic","tos_uri":"","updated_at":"2022-11-09T01:00:35+00:00","userinfo_signed_response_alg":"none"}

(the important part is probably "jwks":[] - jwks is getting serialized as an array)

I've also dumped a repro here: https://github.com/AlbinoDrought/repro-ory-sdk-224

Cheers!

AlbinoDrought commented 1 year ago

Loosely related, but adminRevokeOAuth2ConsentSessions* also has a serialization issue:

    /**
     * Create request for operation 'adminRevokeOAuth2ConsentSessions'
     *
     * @param  string $subject The subject (Subject) whose consent sessions should be deleted. (required)
     * @param  string $client If set, deletes only those consent sessions by the Subject that have been granted to the specified OAuth 2.0 Client ID (optional)
     * @param  bool $all If set to &#x60;true&#x60; deletes all consent sessions by the Subject that have been granted. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    public function adminRevokeOAuth2ConsentSessionsRequest($subject, $client = null, $all = null)
    {
        // [ ...]
        // query params
        if ($all !== null) {
            if('form' === 'form' && is_array($all)) {
                foreach($all as $key => $value) {
                    $queryParams[$key] = $value;
                }
            }
            else {
                $queryParams['all'] = $all;
            }
        }
        // [...]
    }

$all is typed as bool, but gets serialized to 1 in the query string.

Hydra explicitly checks for "true', causing a 400 Bad Request to be emitted when it receives the "1":

{
   "class": "Ory\\Client\\ApiException",
   "message": "[400] Client error: DELETE http://hydra:4445/admin/oauth2/auth/sessions/consent?subject=1234&all=1 resulted in a 400 Bad Request response:\n{\"error\":\"invalid_request\",\"error_description\":\"The request is missing a required parameter, includes an invalid paramet (truncated...)\n",
   "code": 400,
   "file": "/app/vendor/ory/client/lib/Api/V0alpha2Api.php:11172",
   "trace": [
       "/app/vendor/ory/client/lib/Api/V0alpha2Api.php:11147",
       "..."
   ]
}

Passing "true" would probably work but this gets rejected by static analysis tools:

ERROR: InvalidScalarArgument - Argument 3 of Ory\Client\Api\V0alpha2Api::adminRevokeOAuth2ConsentSessions expects bool|null, "true" provided (see https://psalm.dev/012) $this->client->adminRevokeOAuth2ConsentSessions($id, null, "true");