BookStackApp/BookStack · error · Error

Invalid SP metadata:

Error message

Invalid SP metadata: 

What it means

Thrown by Saml2Service::metadata() when the OneLogin toolkit's Settings::validateMetadata() reports problems with the generated Service Provider (SP) XML metadata. The toolkit builds SP metadata from BookStack's SAML settings; if the resulting document fails validation (missing or invalid entityID, bad certificate format, invalid URLs), an Error with code METADATA_SP_INVALID is thrown. This endpoint is what admins feed to their IdP, so it blocks SAML setup entirely.

Source

Thrown at app/Access/Saml2Service.php:164

        $defaultBookStackRedirect = $this->loginService->logout();

        return $samlRedirect ?? $defaultBookStackRedirect;
    }

    /**
     * Get the metadata for this service provider.
     *
     * @throws Error
     */
    public function metadata(): string
    {
        $toolKit = $this->getToolkit(true);
        $settings = $toolKit->getSettings();
        $metadata = $settings->getSPMetadata();
        $errors = $settings->validateMetadata($metadata);

        if (!empty($errors)) {
            throw new Error(
                'Invalid SP metadata: ' . implode(', ', $errors),
                Error::METADATA_SP_INVALID
            );
        }

        return $metadata;
    }

    /**
     * Load the underlying Onelogin SAML2 toolkit.
     *
     * @throws Error
     * @throws Exception
     */
    protected function getToolkit(bool $spOnly = false): Auth
    {
        $settings = $this->config['onelogin'];
        $overrides = $this->config['onelogin_overrides'] ?? [];

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Read the error list in the message — validateMetadata names each invalid field; fix those specific SAML2_SP_* options (entityId, assertion URL, etc.) in .env or settings.
  2. If SP signing is required, ensure SAML2_SP_x509 and SAML2_SP_privateKey contain full PEM blocks including '-----BEGIN CERTIFICATE-----'/'-----BEGIN PRIVATE KEY-----' headers and correct line breaks.
  3. Regenerate a proper self-signed cert pair: 'openssl req -x509 -newkey rsa:2048 -nodes -keyout sp.key -out sp.crt -days 3650 -subj "/CN=bookstack"' and paste the PEM contents.
  4. Confirm SAML2_SP_entityId is a non-empty unique URI and the ACS/SLS URLs are absolute, well-formed URLs matching your BookStack instance.
  5. Re-fetch the metadata URL after fixes and validate the XML at the IdP before retrying login.

Example fix

// before (.env, cert pasted without PEM headers)
SAML2_SP_x509=MIIC7jCCAdOgAwIBAgIU...

// after (.env, complete PEM)
SAML2_SP_x509=-----BEGIN CERTIFICATE-----
MIIC7jCCAdOgAwIBAgIU...
-----END CERTIFICATE-----
Defensive patterns

Strategy: validation

Validate before calling

// Validate SP SAML options before calling metadata()/enabling SAML:
$required = ['SAML2_IDP_entityId', 'SAML2_IDP_sso', 'SAML2_SP_entityId'];
foreach ($required as $opt) {
    if (empty(env($opt))) {
        throw new \RuntimeException("Missing SAML option: {$opt}");
    }
}
// If SP signing enabled, require full PEM blocks:
$cert = env('SAML2_SP_x509');
if ($cert !== null && !str_starts_with($cert, '-----BEGIN CERTIFICATE-----')) {
    throw new \RuntimeException('SAML2_SP_x509 must be a full PEM certificate');
}

Try / catch

use OneLogin\Saml2\Error as Saml2Error;

try {
    $xml = $saml2Service->metadata();
} catch (Saml2Error $e) {
    if ($e->getCode() === Saml2Error::METADATA_SP_INVALID) {
        abort(500, 'SP metadata invalid: ' . $e->getMessage() . ' — check SAML2_SP_* options and PEM certs.');
    }
    throw $e;
}

Prevention

When it happens

Trigger: Visiting the /saml2/metadata route; getToolkit(true) builds SP-only settings and getSPMetadata() produces XML that validateMetadata() rejects — e.g. missing required SAML2_* env options (entityId, SP cert/private key with strict settings), an x509 cert that isn't valid PEM, entityId or URLs that are empty/not valid URIs, or malformed user-provided settings arrays.

Common situations: Fresh BookStack SAML setup where the SP certificate/private key options were pasted without headers or with wrong line endings; entityId left unset or containing spaces; SAML enabled (SAML2_ENABLED=true) before all required SP options were configured; cert generated with a tool producing DER instead of PEM; trailing slashes/typos in the callback URL options.

Related errors


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