BookStackApp/BookStack · error · OidcInvalidTokenException

Missing token subject value

Error message

Missing token subject value

What it means

The 'sub' (Subject) claim uniquely identifies the end user and is REQUIRED by the OIDC spec. As a custom check, validateTokenClaims throws when the token payload has no 'sub' value, because the application cannot attribute the session to any user.

Source

Thrown at app/Access/Oidc/OidcIdToken.php:86

        }

        $dayAgo = time() - 86400;
        $iat = intval($this->payload['iat']);
        if ($iat > ($now + $skewSeconds) || $iat < $dayAgo) {
            throw new OidcInvalidTokenException('Token issue at time is not recent or is invalid');
        }

        // 7. If the acr Claim was requested, the Client SHOULD check that the asserted Claim Value is appropriate.
        // The meaning and processing of acr Claim Values is out of scope for this document.
        // NOTE: Not used for our case here. acr is not requested.

        // 8. When a max_age request is made, the Client SHOULD check the auth_time Claim value and request
        // re-authentication if it determines too much time has elapsed since the last End-User authentication.
        // NOTE: Not used for our case here. A max_age request is not made.

        // Custom: Ensure the "sub" (Subject) Claim exists and has a value.
        if (empty($this->payload['sub'])) {
            throw new OidcInvalidTokenException('Missing token subject value');
        }
    }
}

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Fix the IdP to include a non-empty 'sub' claim per OIDC Core spec
  2. Update test token fixtures to include 'sub'
  3. Check no proxy/middleware removes claims from the id_token
  4. Map the correct user identifier if the IdP uses a different claim and you control token minting

Example fix

// before (test fixture payload)
['iss' => $iss, 'aud' => $aud, 'exp' => time()+3600, 'iat' => time()]
// after
['iss' => $iss, 'aud' => $aud, 'exp' => time()+3600, 'iat' => time(), 'sub' => 'user-123']
Defensive patterns

Strategy: validation

Validate before calling

if (empty($payload['sub'])) { throw new \RuntimeException('ID token missing sub claim'); }

Try / catch

try { $token->validate($now); } catch (OidcInvalidTokenException $e) { if ($e->getMessage() === 'Missing token subject value') { /* reject login; report non-conformant IdP */ } throw $e; }

Prevention

When it happens

Trigger: validate() on an ID token whose payload lacks 'sub' or has it empty/null.

Common situations: Non-conformant IdP omitting subject; tokens generated by custom/legacy auth services; test fixtures missing 'sub'; claim-filtering middleware stripping the subject for privacy.

Related errors


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