{"record":{"id":"23994f946f0d8515","repo":"BookStackApp/BookStack","slug":"could-not-parse-out-a-valid-signature-within-the-p","errorCode":null,"errorMessage":"Could not parse out a valid signature within the provided token","messagePattern":"Could not parse out a valid signature within the provided token","errorType":"exception","errorClass":"OidcInvalidTokenException","httpStatus":null,"severity":"error","filePath":"app/Access/Oidc/OidcJwtWithClaims.php","lineNumber":111,"sourceCode":"        $this->payload = $claims;\n    }\n\n    /**\n     * Validate the structure of the given token and ensure we have the required pieces.\n     * As per https://datatracker.ietf.org/doc/html/rfc7519#section-7.2.\n     *\n     * @throws OidcInvalidTokenException\n     */\n    protected function validateTokenStructure(): void\n    {\n        foreach (['header', 'payload'] as $prop) {\n            if (empty($this->$prop)) {\n                throw new OidcInvalidTokenException(\"Could not parse out a valid {$prop} within the provided token\");\n            }\n        }\n\n        if (empty($this->signature)) {\n            throw new OidcInvalidTokenException('Could not parse out a valid signature within the provided token');\n        }\n    }\n\n    /**\n     * Validate the signature of the given token and ensure it validates against the provided key.\n     *\n     * @throws OidcInvalidTokenException\n     */\n    protected function validateTokenSignature(): void\n    {\n        if ($this->header['alg'] !== 'RS256') {\n            throw new OidcInvalidTokenException(\"Only RS256 signature validation is supported. Token reports using {$this->header['alg']}\");\n        }\n\n        $parsedKeys = array_map(function ($key) {\n            try {\n                return new OidcJwtSigningKey($key);\n            } catch (OidcInvalidKeyException $e) {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Oidc/OidcJwtWithClaims.php#L93-L129","documentation":"This is the signature-counterpart of the structure check in validateTokenStructure: after header and payload parse, the third dot-separated segment must be a non-empty signature. If empty, OidcInvalidTokenException is thrown. An unsigned/empty-signature token cannot be verified and is rejected early.","triggerScenarios":"A JWT supplied to the OIDC validation flow whose third segment is empty or absent — e.g. 'xxx.yyy.' — typically an unsecured (alg:none style) or truncated token.","commonSituations":"Client stripping the signature; provider issuing unsigned tokens (alg none); token truncated in transit or storage (column too short, query-string clipping); pasting only part of the token during testing.","solutions":["Ensure the full three-part id_token is transmitted and stored unmodified (check truncation in DB columns/URLs)","Confirm the IdP signs tokens (RS256) and is not issuing alg:none tokens","Obtain a fresh id_token and retry the flow"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function hasJwtSignature(string $token): bool {\n    $parts = explode('.', $token);\n    return count($parts) === 3 && $parts[2] !== '';\n}","typeGuard":"function isSignedJwt(mixed $token): bool { return is_string($token) && substr_count($token, '.') === 2 && end(explode('.', $token)) !== ''; }","tryCatchPattern":"try {\n    $jwt->validate($token);\n} catch (\\BookStack\\Access\\Oidc\\OidcInvalidTokenException $e) {\n    if (str_contains($e->getMessage(), 'signature')) {\n        // token is unsigned or truncated; refetch / reject\n    }\n}","preventionTips":["Reject tokens without a third segment client-side before sending for validation","Ensure the IdP signs tokens (RS256, not none)","Store/transmit tokens unaltered — beware trimming, escaping, or column truncation"],"tags":["php","oidc","jwt","signature","malformed-token"],"backgroundTag":"malformed-jwt","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}