{"record":{"id":"980d993b6c409e3b","repo":"appwrite/appwrite","slug":"invalid-secret-980d99","errorCode":null,"errorMessage":"Invalid secret","messagePattern":"Invalid secret","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Appwrite/Auth/OAuth2/Microsoft.php","lineNumber":192,"sourceCode":"            $headers = ['Authorization: Bearer ' . \\urlencode($accessToken)];\n            $user = $this->request('GET', 'https://graph.microsoft.com/v1.0/me', $headers);\n            $this->user = \\json_decode($user, true);\n        }\n\n        return $this->user;\n    }\n\n    /**\n     * Decode the JSON stored in appSecret\n     *\n     * @return array\n     */\n    protected function getAppSecret(): array\n    {\n        try {\n            $secret = \\json_decode($this->appSecret, true, 512, JSON_THROW_ON_ERROR);\n        } catch (\\Throwable $th) {\n            throw new \\Exception('Invalid secret');\n        }\n        return $secret;\n    }\n\n    /**\n     * Extracts the Client Secret from the JSON stored in appSecret\n     *\n     * @return string\n     */\n    protected function getClientSecret(): string\n    {\n        $secret = $this->getAppSecret();\n\n        return $secret['clientSecret'] ?? '';\n    }\n\n    /**\n     * Extracts the Tenant Id from the JSON stored in appSecret.","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/appwrite/appwrite/blob/cd368e707d4b492bc5e8e9c0f8ecbc5b741c4bf4/src/Appwrite/Auth/OAuth2/Microsoft.php#L174-L210","documentation":"Thrown by Microsoft::getAppSecret() when json_decode() of the stored appSecret fails. The Microsoft adapter expects appSecret to be a JSON object (containing at least 'clientSecret' and 'tenantID'); JSON_THROW_ON_ERROR converts any syntax error into a JsonException, which is caught and re-thrown as this generic Exception. It fires on the first access to any field pulled from the secret (clientSecret, tenantID).","triggerScenarios":"Any call to getClientSecret() or getTenantID() on a Microsoft adapter whose appSecret is not valid JSON: getLoginURL(), getTokens(), refreshTokens(), and verifyCredentials() all reach getAppSecret(). Triggered when a user starts a Microsoft OAuth2 login or the Console validates a provider whose secret was saved as a plain string, with a trailing comma, single-quoted, HTML-escaped, or otherwise malformed.","commonSituations":"Secret entered as a bare client-secret string instead of JSON; JSON hand-edited and broken (trailing comma, unescaped quotes); copy-paste from a webpage that inserted smart-quotes or HTML entities; secret saved through an older API that accepted raw strings; leading/trailing whitespace or BOM in the value.","solutions":["Re-enter the Microsoft appSecret in the Console as well-formed JSON, e.g. {\"clientSecret\":\"...\",\"tenantID\":\"...\"}.","Run the value through json_decode locally (or a JSON linter) to find the exact syntax error before saving.","Ensure no HTML entity encoding, smart quotes, or stray whitespace wraps the value; paste as plain text.","If migrating from a raw-string format, wrap the existing secret into the JSON shape and re-save."],"exampleFix":"// before\n$appSecret = 'clientSecret=abc;tenantID=000-000'; // not JSON\n// after\n$appSecret = '{\"clientSecret\":\"abc\",\"tenantID\":\"00000000-0000-0000-0000-000000000000\"}';","handlingStrategy":"validation","validationCode":"// Validate that appSecret parses as JSON before persisting it for the Microsoft provider.\nfunction validateMicrosoftSecretJSON(string $appSecret): void {\n    $decoded = json_decode($appSecret, true, 512, JSON_THROW_ON_ERROR);\n    if (!is_array($decoded)) {\n        throw new InvalidArgumentException('Microsoft appSecret must decode to a JSON object.');\n    }\n}\n\ntry {\n    validateMicrosoftSecretJSON($appSecret);\n} catch (\\JsonException | \\InvalidArgumentException $e) {\n    // reject the save; surface the error to the admin\n}","typeGuard":null,"tryCatchPattern":"// Around any code path that reads the Microsoft secret:\ntry {\n    $clientSecret = $microsoft->getClientSecret();\n} catch (\\Exception $e) {\n    if ($e->getMessage() === 'Invalid secret') {\n        throw new ProviderConfigurationException('Microsoft appSecret is not valid JSON; re-enter it as {\"clientSecret\":...,\"tenantID\":...}', 0, $e);\n    }\n    throw $e;\n}","preventionTips":["Never store the Microsoft appSecret as a plain string; always use the JSON object shape.","Add a JSON-schema validation step in the API/Console save handler for the Microsoft provider.","Pin a contract test that builds the adapter from sample config and asserts getAppSecret() returns an array.","Paste secrets as plain text from a trusted source to avoid HTML-entity/smart-quote corruption."],"tags":["oauth2","microsoft","configuration","json","secrets"],"backgroundTag":null,"analyzedSha":"cd368e707d4b492bc5e8e9c0f8ecbc5b741c4bf4","analyzedAt":"2026-08-12T14:42:48.571Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}