{"record":{"id":"0749251b4f56932d","repo":"BookStackApp/BookStack","slug":"issuer-value-must-start-with-https","errorCode":null,"errorMessage":"Issuer value must start with https://","messagePattern":"Issuer value must start with https://","errorType":"validation","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"app/Access/Oidc/OidcProviderSettings.php","lineNumber":64,"sourceCode":"        }\n    }\n\n    /**\n     * Validate any core, required properties have been set.\n     *\n     * @throws InvalidArgumentException\n     */\n    protected function validateInitial(): void\n    {\n        $required = ['clientId', 'clientSecret', 'issuer'];\n        foreach ($required as $prop) {\n            if (empty($this->$prop)) {\n                throw new InvalidArgumentException(\"Missing required configuration \\\"{$prop}\\\" value\");\n            }\n        }\n\n        if (!str_starts_with($this->issuer, 'https://')) {\n            throw new InvalidArgumentException('Issuer value must start with https://');\n        }\n    }\n\n    /**\n     * Perform a full validation on these settings.\n     *\n     * @throws InvalidArgumentException\n     */\n    public function validate(): void\n    {\n        $this->validateInitial();\n\n        $required = ['keys', 'tokenEndpoint', 'authorizationEndpoint'];\n        foreach ($required as $prop) {\n            if (empty($this->$prop)) {\n                throw new InvalidArgumentException(\"Missing required configuration \\\"{$prop}\\\" value\");\n            }\n        }","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Oidc/OidcProviderSettings.php#L46-L82","documentation":"validateInitial() requires the OIDC issuer URL to use HTTPS, because the issuer is the trust root for discovery and token validation. A plain http:// (or otherwise malformed, e.g. missing scheme) issuer value is rejected immediately with an InvalidArgumentException.","triggerScenarios":"Setting oidc.issuer (OIDC_ISSUER) to an http:// URL, a bare hostname without scheme, a URL with a leading/trailing typo, or an empty-but-truthy value not starting with 'https://'.","commonSituations":"Local/dev IdPs served over plain HTTP (e.g. http://localhost:8080/realms/test) being pointed at in production config; copy-paste of issuer from docs losing the scheme; issuer behind an offloading proxy whose advertised URL is http.","solutions":["Set OIDC_ISSUER to a full https:// URL exactly matching the IdP's advertised issuer (including realm/path).","For local development, stand up the IdP behind HTTPS (e.g. reverse proxy with TLS, mkcert) instead of downgrading the check.","Verify the exact issuer string against the IdP's .well-known/openid-configuration 'issuer' field — it must match character-for-character.","Ensure no whitespace or quoting artifacts got into the env value; run php artisan config:clear afterwards."],"exampleFix":"# before\nOIDC_ISSUER=http://keycloak.local:8080/realms/main\n# after\nOIDC_ISSUER=https://keycloak.local/realms/main","handlingStrategy":"validation","validationCode":"$issuer = config('oidc.issuer');\nif (!is_string($issuer) || !str_starts_with($issuer, 'https://')) {\n    throw new RuntimeException('OIDC issuer must be a full https:// URL');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $settings->validate();\n} catch (InvalidArgumentException $e) {\n    Log::error('OIDC issuer invalid: ' . $e->getMessage());\n}\n// or pre-check: assert(str_starts_with(config('oidc.issuer') ?? '', 'https://'));","preventionTips":["Always configure the issuer exactly as advertised by the IdP (https:// including realm/path).","Serve local/dev IdPs over HTTPS (mkcert + reverse proxy) rather than http.","Trim whitespace/quotes from env values.","Copy the issuer string straight from /.well-known/openid-configuration."],"tags":["configuration","https","oidc","validation"],"backgroundTag":"insecure-url-rejected","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}