diff --git a/oidc/class/oidc.class.php b/oidc/class/oidc.class.php index 12fa2af..ef34e4d 100644 --- a/oidc/class/oidc.class.php +++ b/oidc/class/oidc.class.php @@ -101,6 +101,20 @@ class OIDC extends FOGController 'issuer', 'clientId' ]; + /** + * clientId ends in "id" without being a foreign key. + * + * FOGController::save() reads a key ending in "id" as an integer id + * unless the model says otherwise. A client id is a string the provider + * chooses -- "fog-web", or a GUID on Entra -- so without this every + * create failed with "Required database field is empty: clientId" about + * a field that was filled in. Needs fogproject#1153. + * + * @var array + */ + protected $databaseFieldsNotInt = [ + 'clientId' + ]; /** * Validate before storing. * diff --git a/tests/oidc-provider-safety.test.php b/tests/oidc-provider-safety.test.php index 5b2b803..ebfe37c 100644 --- a/tests/oidc-provider-safety.test.php +++ b/tests/oidc-provider-safety.test.php @@ -297,6 +297,29 @@ function () { ); } +/* + * clientId must stay declared as a string. + * + * FOGController::save() reads any key ending in "id" as an integer foreign + * key unless the model opts out, and clientId is required -- so dropping the + * opt-out does not degrade anything, it makes creating a provider impossible, + * reported as "Required database field is empty: clientId" about a field the + * admin filled in. That is a whole feature off, so it is pinned here rather + * than left to be rediscovered. Needs fogproject#1153. + */ +$declared = []; +if (property_exists('OIDC', 'databaseFieldsNotInt')) { + $notInt = new \ReflectionProperty('OIDC', 'databaseFieldsNotInt'); + $notInt->setAccessible(true); + $declared = array_map('strtolower', (array)$notInt->getValue(new OIDC())); +} +if (!in_array('clientid', $declared, true)) { + fail( + 'OIDC does not declare clientId in $databaseFieldsNotInt, so ' + . 'save() will reject every provider whose client id is not a number' + ); +} + if (count($fails) > 0) { fwrite(STDERR, 'FAIL: ' . count($fails) . " problem(s):\n"); foreach ($fails as $f) {