{"id":15662233,"url":"https://github.com/phryneas/ssr-only-secrets","last_synced_at":"2025-04-09T20:03:59.205Z","repository":{"id":215436575,"uuid":"738920759","full_name":"phryneas/ssr-only-secrets","owner":"phryneas","description":"This package provides a way to pass secrets from Server Components into the SSR-run of Client Components, without them being accessible in the browser.","archived":false,"fork":false,"pushed_at":"2025-02-15T16:46:47.000Z","size":111,"stargazers_count":26,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-09T20:03:54.372Z","etag":null,"topics":["library"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/ssr-only-secrets","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phryneas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-04T11:01:36.000Z","updated_at":"2025-03-28T15:01:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"ba5c558a-a340-4565-b922-46d3a2a97018","html_url":"https://github.com/phryneas/ssr-only-secrets","commit_stats":null,"previous_names":["phryneas/ssr-only-secrets"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phryneas%2Fssr-only-secrets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phryneas%2Fssr-only-secrets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phryneas%2Fssr-only-secrets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phryneas%2Fssr-only-secrets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phryneas","download_url":"https://codeload.github.com/phryneas/ssr-only-secrets/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103864,"owners_count":21048245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["library"],"created_at":"2024-10-03T13:30:47.188Z","updated_at":"2025-04-09T20:03:59.181Z","avatar_url":"https://github.com/phryneas.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ssr-only-secrets\r\n\r\nThis package provides a way to pass secrets from Server Components into the SSR-run of Client Components without them being accessible in the browser.\r\n\r\nThis technique was inspired by [this comment](https://github.com/apollographql/apollo-client-nextjs/issues/85#issuecomment-1753442277) by [@Stevemoretz](https://github.com/Stevemoretz)\u003c!-- --\u003e.\r\n\r\n\u003ch2\u003eUsage:\u003c/h2\u003e\r\n\r\nInstall the package\r\n\r\n```sh\r\nnpm i ssr-only-secrets\r\n```\r\nGenerate a jwk-formatted AES-CBC key, e.g. by running\r\n\r\n```js\r\ncrypto.subtle\r\n  .generateKey(\r\n    {\r\n      name: \"AES-CBC\",\r\n      length: 256,\r\n    },\r\n    true,\r\n    [\"encrypt\", \"decrypt\"]\r\n  )\r\n  .then((key) =\u003e crypto.subtle.exportKey(\"jwk\", key))\r\n  .then(JSON.stringify)\r\n  .then(console.log);\r\n```\r\nand store the result in an environment variable, e.g. `SECRET_KEY_VAR`\u003c!-- --\u003e, e.g. by writing it into your `.env.local`\u003c!-- --\u003e.\r\n\r\n```env\r\nSECRET_KEY_VAR={\"alg\":\"A256CBC\",\"ext\":true,\"k\":\"...\",\"key_ops\":[\"encrypt\",\"decrypt\"],\"kty\":\"oct\"}\r\n```\r\nNow, you can pass \"cloaked secrets\" from your Server Components into the SSR-run of your Client Components, without them being accessible in your Client Components in the browser.\r\n\r\n## Example\r\n\r\nIn a Server Component:\r\n\r\n```jsx\r\nimport { cloakSSROnlySecret } from \"ssr-only-secrets\";\r\n\r\nconst MyServerComponent = () =\u003e {\r\n    const secretValue = \"my secret value\"\r\n    return \u003cClientComponent ssrOnlySecret={cloakSSROnlySecret(secretValue, \"SECRET_KEY_VAR\")} /\u003e\r\n}\r\n```\r\nAnd in a Client Component\r\n\r\n```jsx\r\nimport { useSSROnlySecret } from \"ssr-only-secrets\";\r\n\r\nconst ClientComponent = ({ssrOnlySecret}, \"SECRET_KEY_VAR\") =\u003e {\r\n    const value = useSSROnlySecret(ssrOnlySecret);\r\n    console.log(value); // during SSR, this logs \"my secret value\", but in the browser, it logs \"undefined\"\r\n}\r\n```\r\nAlternatively, you can decrypt the secret in your code by calling `readSSROnlySecret`\u003c!-- --\u003e, e.g. in an Apollo Link:\r\n\r\n```jsx\r\nconst value = await readSSROnlySecret(ssrOnlySecret)\r\n```\r\n\r\n## Functions\r\n\r\n|  Function | Description |\r\n|  --- | --- |\r\n|  [cloakSSROnlySecret(secret, encryptionEnvVarName)](https://github.com/phryneas/ssr-only-secrets/blob/main/docs/ssr-only-secrets.cloakssronlysecret.md) | \u003cp\u003eEncrypts a secret so that it can be passed from Server Components into the SSR-run of Client Components without them being accessible in the browser.\u003c/p\u003e\u003cp\u003eUse \u003ccode\u003euseSSROnlySecret\u003c/code\u003e or \u003ccode\u003ereadSSROnlySecret\u003c/code\u003e to decrypt the secret in your Client Component.\u003c/p\u003e\u003cp\u003eOnly available in Server Components.\u003c/p\u003e |\r\n|  [readSSROnlySecret(cloakedSecret, encryptionEnvVarName)](https://github.com/phryneas/ssr-only-secrets/blob/main/docs/ssr-only-secrets.readssronlysecret.md) | \u003cp\u003eDecrypts a secret that was created in a Server Component using \u003ccode\u003ecloakSSROnlySecret\u003c/code\u003e.\u003c/p\u003e\u003cp\u003eCalling this in a Browser environment will always return \u003ccode\u003eundefined\u003c/code\u003e.\u003c/p\u003e\u003cp\u003eOnly available in Client Components.\u003c/p\u003e |\r\n|  [useSSROnlySecret(cloakedSecret, encryptionEnvVarName)](https://github.com/phryneas/ssr-only-secrets/blob/main/docs/ssr-only-secrets.usessronlysecret.md) | \u003cp\u003eDecrypts a secret that was created in a Server Component using \u003ccode\u003ecloakSSROnlySecret\u003c/code\u003e. If called during SSR, this hook will briefly suspend your component and then return the decrypted secret.\u003c/p\u003e\u003cp\u003eCalling this in a Browser environment will always return \u003ccode\u003eundefined\u003c/code\u003e.\u003c/p\u003e\u003cp\u003eOnly available in Client Components.\u003c/p\u003e |\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphryneas%2Fssr-only-secrets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphryneas%2Fssr-only-secrets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphryneas%2Fssr-only-secrets/lists"}