BookStackApp/BookStack · error · IdentityProviderException

{$data['error'] ?? $response->getReasonPhrase()}

Error message

{$data['error'] ?? $response->getReasonPhrase()}

What it means

This error comes from checkResponse in OidcOAuthProvider (BookStack's league/oauth2-client based provider). When the identity provider's token or authorization response has an HTTP status >= 400 or an 'error' key in the decoded body, an IdentityProviderException is thrown carrying either the provider-reported 'error' string or, if absent, the HTTP reason phrase (e.g. 'Internal Server Error'). It is the library's way of surfacing an OAuth/OIDC protocol-level rejection from the remote IdP.

Source

Thrown at app/Access/Oidc/OidcOAuthProvider.php:91

    }

    /**
     * Returns the string that should be used to separate scopes when building
     * the URL for requesting an access token.
     */
    protected function getScopeSeparator(): string
    {
        return ' ';
    }

    /**
     * Checks a provider response for errors.
     * @throws IdentityProviderException
     */
    protected function checkResponse(ResponseInterface $response, $data): void
    {
        if ($response->getStatusCode() >= 400 || isset($data['error'])) {
            throw new IdentityProviderException(
                $data['error'] ?? $response->getReasonPhrase(),
                $response->getStatusCode(),
                (string) $response->getBody()
            );
        }
    }

    /**
     * Generates a resource owner object from a successful resource owner
     * details request.
     */
    protected function createResourceOwner(array $response, AccessToken $token): ResourceOwnerInterface
    {
        return new GenericResourceOwner($response, '');
    }

    /**
     * Creates an access token from a response.

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Read the IdentityProviderException body (3rd argument) and the provider's logs to see the exact OAuth error code returned.
  2. Verify APP/oidc client_id, client_secret and redirect URI exactly match the IdP application settings.
  3. Re-run the login flow from scratch (fresh authorize request) — invalid_grant errors are often caused by reusing a consumed code or stale session.
  4. Check the IdP status/health and confirm the issuer/token endpoints are reachable over HTTPS.
  5. Compare scopes requested against those allowed by the IdP application.

Example fix

// before: generic failure hard to debug
try { $token = $provider->getAccessToken('authorization_code', [...]); }
catch (IdentityProviderException $e) { Log::error($e->getMessage()); }
// after: log full body from provider for the real cause
try { $token = $provider->getAccessToken('authorization_code', [...]); }
catch (IdentityProviderException $e) {
    Log::error('OIDC provider error: ' . $e->getMessage() . ' body: ' . $e->getResponseBody());
}
Defensive patterns

Strategy: try-catch

Validate before calling

$body = json_decode((string) $response->getBody(), true);
if (($response->getStatusCode() >= 400 || isset($body['error']))) {
    Log::warning('OIDC provider will reject this response', ['status' => $response->getStatusCode(), 'body' => $body]);
}

Type guard

function isProviderError(ResponseInterface $response, ?array $data): bool {
    return $response->getStatusCode() >= 400 || isset($data['error']);
}

Try / catch

try {
    $token = $provider->getAccessToken('authorization_code', ['code' => $code]);
} catch (IdentityProviderException $e) {
    Log::error('OIDC token exchange failed', ['msg' => $e->getMessage(), 'body' => (string) $e->getResponseBody()]);
    return back()->withErrors(['oidc' => 'Authentication with the identity provider failed.']);
}

Prevention

When it happens

Trigger: Any OAuth2 exchange through OidcOAuthProvider (getAccessToken, resource owner fetch, etc.) where the remote OIDC provider returns HTTP >= 400, or returns 200 but includes an 'error' field in the JSON body (e.g. invalid_grant, invalid_client, unauthorized_client).

Common situations: Wrong client_id/client_secret in BookStack OIDC config causing invalid_client; expired or replayed authorization code causing invalid_grant; misconfigured redirect URI; IdP outage returning a 5xx; clock skew invalidating tokens.


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