BookStackApp/BookStack · error · OidcInvalidKeyException

Unexpected type of key value provided

Error message

Unexpected type of key value provided

What it means

OidcJwtSigningKey's constructor accepts either a JWK array or a 'file://' path string to a key file. Any other argument type (plain string path without file:// scheme, null, object, etc.) cannot be interpreted, so OidcInvalidKeyException is thrown.

Source

Thrown at app/Access/Oidc/OidcJwtSigningKey.php:29

{
    protected PublicKey $key;

    /**
     * Can be created either from a JWK parameter array or local file path to load a certificate from.
     * Examples:
     * 'file:///var/www/cert.pem'
     * ['kty' => 'RSA', 'alg' => 'RS256', 'n' => 'abc123...'].
     *
     * @throws OidcInvalidKeyException
     */
    public function __construct(array|string $jwkOrKeyPath)
    {
        if (is_array($jwkOrKeyPath)) {
            $this->loadFromJwkArray($jwkOrKeyPath);
        } elseif (str_starts_with($jwkOrKeyPath, 'file://')) {
            $this->loadFromPath($jwkOrKeyPath);
        } else {
            throw new OidcInvalidKeyException('Unexpected type of key value provided');
        }
    }

    /**
     * @throws OidcInvalidKeyException
     */
    protected function loadFromPath(string $path): void
    {
        try {
            $key = PublicKeyLoader::load(
                file_get_contents($path)
            );
        } catch (\Exception $exception) {
            throw new OidcInvalidKeyException("Failed to load key from file path with error: {$exception->getMessage()}");
        }

        if (!$key instanceof RSA) {
            throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Prefix the path with 'file://' e.g. new OidcJwtSigningKey('file:///path/to/key.pem')
  2. Pass a decoded JWK array instead if you have the JWK (from discovery jwks_uri)
  3. If you have raw PEM contents, write them to a temp/known file and pass the file:// path
  4. Log/var_dump the value to confirm what is actually being passed (null vs string)

Example fix

// before
$key = new OidcJwtSigningKey('/etc/oidc/key.pem');
// after
$key = new OidcJwtSigningKey('file:///etc/oidc/key.pem');
Defensive patterns

Strategy: type-guard

Validate before calling

$value = config('oidc.signing_key');
if (!(is_array($value) || (is_string($value) && str_starts_with($value, 'file://')))) { throw new \InvalidArgumentException('key must be JWK array or file:// path'); }

Type guard

function isValidKeyValue(mixed $v): bool { return is_array($v) || (is_string($v) && str_starts_with($v, 'file://')); }

Try / catch

try { $key = new OidcJwtSigningKey($jwkOrPath); } catch (OidcInvalidKeyException $e) { /* fix config: expected JWK array or file:// string */ throw $e; }

Prevention

When it happens

Trigger: new OidcJwtSigningKey('/path/to/key.pem') (missing file:// prefix), new OidcJwtSigningKey($keyString), new OidcJwtSigningKey(null), or passing any non-array, non-file:// value.

Common situations: Config value holding a raw filesystem path without the file:// scheme; passing PEM/DER key contents directly as a string; config not loaded so null is passed; wiring the wrong config variable.

Related errors


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/84a7c41ff369a885. Report an issue: GitHub.