OIDC param name improvement

This commit is contained in:
Matej Bačo
2026-05-06 11:24:53 +02:00
parent ff518a055f
commit dcef7ef559
4 changed files with 76 additions and 59 deletions
@@ -82,13 +82,13 @@ class Update extends Base
'hint' => '',
],
[
'$id' => 'tokenUrl',
'$id' => 'tokenURL',
'name' => 'Token URL',
'example' => 'https://myoauth.com/oauth2/token',
'hint' => '',
],
[
'$id' => 'userInfoUrl',
'$id' => 'userInfoURL',
'name' => 'User Info URL',
'example' => 'https://myoauth.com/oauth2/userinfo',
'hint' => '',
@@ -127,8 +127,8 @@ class Update extends Base
->param(static::getClientSecretParamName(), null, new Nullable(new Text(512, 0)), static::getClientSecretDescription(), optional: true)
->param('wellKnownURL', null, new Nullable(new URL(allowEmpty: true)), 'OpenID Connect well-known configuration URL. When provided, authorization, token, and user info endpoints can be discovered automatically. For example: https://myoauth.com/.well-known/openid-configuration', optional: true)
->param('authorizationURL', null, new Nullable(new URL(allowEmpty: true)), 'OpenID Connect authorization endpoint URL. Required when wellKnownURL is not provided. For example: https://myoauth.com/oauth2/authorize', optional: true)
->param('tokenUrl', null, new Nullable(new URL(allowEmpty: true)), 'OpenID Connect token endpoint URL. Required when wellKnownURL is not provided. For example: https://myoauth.com/oauth2/token', optional: true)
->param('userInfoUrl', null, new Nullable(new URL(allowEmpty: true)), 'OpenID Connect user info endpoint URL. Required when wellKnownURL is not provided. For example: https://myoauth.com/oauth2/userinfo', optional: true)
->param('tokenURL', null, new Nullable(new URL(allowEmpty: true)), 'OpenID Connect token endpoint URL. Required when wellKnownURL is not provided. For example: https://myoauth.com/oauth2/token', optional: true, aliases: ['tokenUrl'])
->param('userInfoURL', null, new Nullable(new URL(allowEmpty: true)), 'OpenID Connect user info endpoint URL. Required when wellKnownURL is not provided. For example: https://myoauth.com/oauth2/userinfo', optional: true, aliases: ['userInfoUrl'])
->param('enabled', null, new Nullable(new Boolean()), 'OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid.', true)
->inject('response')
->inject('dbForPlatform')
@@ -151,8 +151,8 @@ class Update extends Base
static::getClientSecretParamName() => '',
'wellKnownURL' => $decoded['wellKnownEndpoint'] ?? '',
'authorizationURL' => $decoded['authorizationEndpoint'] ?? '',
'tokenUrl' => $decoded['tokenEndpoint'] ?? '',
'userInfoUrl' => $decoded['userInfoEndpoint'] ?? '',
'tokenURL' => $decoded['tokenEndpoint'] ?? '',
'userInfoURL' => $decoded['userInfoEndpoint'] ?? '',
]);
}
@@ -174,8 +174,8 @@ class Update extends Base
?string $clientSecret,
?string $wellKnownURL,
?string $authorizationURL,
?string $tokenUrl,
?string $userInfoUrl,
?string $tokenURL,
?string $userInfoURL,
?bool $enabled,
Response $response,
Database $dbForPlatform,
@@ -201,8 +201,8 @@ class Update extends Base
'clientSecret' => $clientSecret ?? ($existing['clientSecret'] ?? ''),
'wellKnownEndpoint' => $wellKnownURL ?? ($existing['wellKnownEndpoint'] ?? ''),
'authorizationEndpoint' => $authorizationURL ?? ($existing['authorizationEndpoint'] ?? ''),
'tokenEndpoint' => $tokenUrl ?? ($existing['tokenEndpoint'] ?? ''),
'userInfoEndpoint' => $userInfoUrl ?? ($existing['userInfoEndpoint'] ?? ''),
'tokenEndpoint' => $tokenURL ?? ($existing['tokenEndpoint'] ?? ''),
'userInfoEndpoint' => $userInfoURL ?? ($existing['userInfoEndpoint'] ?? ''),
];
// When enabling, require either wellKnownEndpoint alone, or all three
@@ -215,7 +215,7 @@ class Update extends Base
&& !empty($merged['userInfoEndpoint']);
if (!$hasWellKnown && !$hasAllDiscovery) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Enabling OpenID Connect requires either wellKnownURL, or all of authorizationURL, tokenUrl, and userInfoUrl.');
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Enabling OpenID Connect requires either wellKnownURL, or all of authorizationURL, tokenURL, and userInfoURL.');
}
}
@@ -2,6 +2,7 @@
namespace Appwrite\Utopia\Response\Filters;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Filter;
// Convert 1.9.4 Data format to 1.9.3 format
@@ -10,7 +11,23 @@ class V25 extends Filter
public function parse(array $content, string $model): array
{
return match ($model) {
Response::MODEL_OAUTH2_OIDC => $this->parseOAuth2Oidc($content),
default => $content,
};
}
private function parseOAuth2Oidc(array $content): array
{
if (isset($content['tokenURL'])) {
$content['tokenUrl'] = $content['tokenURL'];
unset($content['tokenURL']);
}
if (isset($content['userInfoURL'])) {
$content['userInfoUrl'] = $content['userInfoURL'];
unset($content['userInfoURL']);
}
return $content;
}
}
@@ -42,13 +42,13 @@ class OAuth2Oidc extends OAuth2Base
'default' => '',
'example' => 'https://myoauth.com/oauth2/authorize',
])
->addRule('tokenUrl', [
->addRule('tokenURL', [
'type' => self::TYPE_STRING,
'description' => 'OpenID Connect token endpoint URL.',
'default' => '',
'example' => 'https://myoauth.com/oauth2/token',
])
->addRule('userInfoUrl', [
->addRule('userInfoURL', [
'type' => self::TYPE_STRING,
'description' => 'OpenID Connect user info endpoint URL.',
'default' => '',
+46 -46
View File
@@ -1651,8 +1651,8 @@ trait OAuth2Base
$this->assertSame(200, $response['headers']['status-code']);
$this->assertSame('https://idp.example.com/.well-known/openid-configuration', $response['body']['wellKnownURL']);
$this->assertArrayHasKey('authorizationURL', $response['body']);
$this->assertArrayHasKey('tokenUrl', $response['body']);
$this->assertArrayHasKey('userInfoUrl', $response['body']);
$this->assertArrayHasKey('tokenURL', $response['body']);
$this->assertArrayHasKey('userInfoURL', $response['body']);
// Cleanup
$this->updateOAuth2('oidc', [
@@ -1660,8 +1660,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1672,15 +1672,15 @@ trait OAuth2Base
'clientId' => 'oidc-discovery',
'clientSecret' => 'oidc-discovery-secret',
'authorizationURL' => 'https://idp.example.com/oauth2/authorize',
'tokenUrl' => 'https://idp.example.com/oauth2/token',
'userInfoUrl' => 'https://idp.example.com/oauth2/userinfo',
'tokenURL' => 'https://idp.example.com/oauth2/token',
'userInfoURL' => 'https://idp.example.com/oauth2/userinfo',
'enabled' => false,
]);
$this->assertSame(200, $response['headers']['status-code']);
$this->assertSame('https://idp.example.com/oauth2/authorize', $response['body']['authorizationURL']);
$this->assertSame('https://idp.example.com/oauth2/token', $response['body']['tokenUrl']);
$this->assertSame('https://idp.example.com/oauth2/userinfo', $response['body']['userInfoUrl']);
$this->assertSame('https://idp.example.com/oauth2/token', $response['body']['tokenURL']);
$this->assertSame('https://idp.example.com/oauth2/userinfo', $response['body']['userInfoURL']);
// Cleanup
$this->updateOAuth2('oidc', [
@@ -1688,8 +1688,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1701,8 +1701,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
@@ -1731,8 +1731,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
@@ -1740,7 +1740,7 @@ trait OAuth2Base
'clientId' => 'oidc-partial',
'clientSecret' => 'oidc-partial-secret',
'authorizationURL' => 'https://idp.example.com/oauth2/authorize',
'tokenUrl' => 'https://idp.example.com/oauth2/token',
'tokenURL' => 'https://idp.example.com/oauth2/token',
'enabled' => true,
]);
@@ -1753,8 +1753,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1785,8 +1785,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1816,8 +1816,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1831,8 +1831,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
@@ -1841,7 +1841,7 @@ trait OAuth2Base
'clientId' => 'oidc-split-discovery',
'clientSecret' => 'oidc-split-discovery-secret',
'authorizationURL' => 'https://idp.example.com/oauth2/authorize',
'tokenUrl' => 'https://idp.example.com/oauth2/token',
'tokenURL' => 'https://idp.example.com/oauth2/token',
'enabled' => false,
]);
@@ -1849,19 +1849,19 @@ trait OAuth2Base
// state must include the two stored URLs + the new one to satisfy
// the all-three-discovery-URLs branch of the enable check.
$enable = $this->updateOAuth2('oidc', [
'userInfoUrl' => 'https://idp.example.com/oauth2/userinfo',
'userInfoURL' => 'https://idp.example.com/oauth2/userinfo',
'enabled' => true,
]);
$this->assertSame(200, $enable['headers']['status-code']);
$this->assertTrue($enable['body']['enabled']);
// Confirm all three URLs ended up persisted (merge wrote the new
// userInfoUrl while preserving the previously stored two).
// userInfoURL while preserving the previously stored two).
$get = $this->getOAuth2Provider('oidc');
$this->assertSame(200, $get['headers']['status-code']);
$this->assertSame('https://idp.example.com/oauth2/authorize', $get['body']['authorizationURL']);
$this->assertSame('https://idp.example.com/oauth2/token', $get['body']['tokenUrl']);
$this->assertSame('https://idp.example.com/oauth2/userinfo', $get['body']['userInfoUrl']);
$this->assertSame('https://idp.example.com/oauth2/token', $get['body']['tokenURL']);
$this->assertSame('https://idp.example.com/oauth2/userinfo', $get['body']['userInfoURL']);
// Cleanup
$this->updateOAuth2('oidc', [
@@ -1869,8 +1869,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1883,8 +1883,8 @@ trait OAuth2Base
'clientSecret' => 'oidc-clear-then-enable-secret',
'wellKnownURL' => 'https://idp.example.com/.well-known/openid-configuration',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
@@ -1907,8 +1907,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1929,16 +1929,16 @@ trait OAuth2Base
$switch = $this->updateOAuth2('oidc', [
'wellKnownURL' => '',
'authorizationURL' => 'https://idp.example.com/oauth2/authorize',
'tokenUrl' => 'https://idp.example.com/oauth2/token',
'userInfoUrl' => 'https://idp.example.com/oauth2/userinfo',
'tokenURL' => 'https://idp.example.com/oauth2/token',
'userInfoURL' => 'https://idp.example.com/oauth2/userinfo',
'enabled' => true,
]);
$this->assertSame(200, $switch['headers']['status-code']);
$this->assertTrue($switch['body']['enabled']);
$this->assertSame('', $switch['body']['wellKnownURL']);
$this->assertSame('https://idp.example.com/oauth2/authorize', $switch['body']['authorizationURL']);
$this->assertSame('https://idp.example.com/oauth2/token', $switch['body']['tokenUrl']);
$this->assertSame('https://idp.example.com/oauth2/userinfo', $switch['body']['userInfoUrl']);
$this->assertSame('https://idp.example.com/oauth2/token', $switch['body']['tokenURL']);
$this->assertSame('https://idp.example.com/oauth2/userinfo', $switch['body']['userInfoURL']);
// Cleanup
$this->updateOAuth2('oidc', [
@@ -1946,8 +1946,8 @@ trait OAuth2Base
'clientSecret' => '',
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
'enabled' => false,
]);
}
@@ -1961,23 +1961,23 @@ trait OAuth2Base
'clientSecret' => 'oidc-clear-secret',
'wellKnownURL' => 'https://idp.example.com/.well-known/openid-configuration',
'authorizationURL' => 'https://idp.example.com/oauth2/authorize',
'tokenUrl' => 'https://idp.example.com/oauth2/token',
'userInfoUrl' => 'https://idp.example.com/oauth2/userinfo',
'tokenURL' => 'https://idp.example.com/oauth2/token',
'userInfoURL' => 'https://idp.example.com/oauth2/userinfo',
'enabled' => false,
]);
$response = $this->updateOAuth2('oidc', [
'wellKnownURL' => '',
'authorizationURL' => '',
'tokenUrl' => '',
'userInfoUrl' => '',
'tokenURL' => '',
'userInfoURL' => '',
]);
$this->assertSame(200, $response['headers']['status-code']);
$this->assertSame('', $response['body']['wellKnownURL']);
$this->assertSame('', $response['body']['authorizationURL']);
$this->assertSame('', $response['body']['tokenUrl']);
$this->assertSame('', $response['body']['userInfoUrl']);
$this->assertSame('', $response['body']['tokenURL']);
$this->assertSame('', $response['body']['userInfoURL']);
// Cleanup
$this->updateOAuth2('oidc', [