diff --git a/.changeset/seamless-service-token-env.md b/.changeset/seamless-service-token-env.md new file mode 100644 index 0000000..91d6641 --- /dev/null +++ b/.changeset/seamless-service-token-env.md @@ -0,0 +1,7 @@ +--- +"@seamless-auth/express": patch +"@seamless-auth/fastify": patch +"@seamless-auth/nextjs": patch +--- + +The README examples read the service secret from `SEAMLESS_SERVICE_TOKEN` instead of `SERVICE_SECRET`. The auth server still reads `API_SERVICE_TOKEN`; both hold the same value. The adapters read no environment variables, so nothing changes at runtime. diff --git a/packages/express/README.md b/packages/express/README.md index 416a9b1..d717350 100644 --- a/packages/express/README.md +++ b/packages/express/README.md @@ -64,7 +64,7 @@ app.use( createSeamlessAuthServer({ authServerUrl: process.env.AUTH_SERVER_URL!, cookieSecret: process.env.COOKIE_SECRET!, - serviceSecret: process.env.SERVICE_SECRET!, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN!, audience: process.env.AUTH_SERVER_URL!, }), ); @@ -317,7 +317,7 @@ app.use( createSeamlessAuthServer({ authServerUrl: "https://identifier.seamlessauth.com", cookieSecret: process.env.COOKIE_SECRET, - serviceSecret: process.env.SERVICE_SECRET, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN, audience: "https://identifier.seamlessauth.com", // local HTTP dev only, never in a deployed environment cookieSecure: false, @@ -356,7 +356,7 @@ app.use( createSeamlessAuthServer({ authServerUrl: "https://identifier.seamlessauth.com", cookieSecret: process.env.COOKIE_SECRET, - serviceSecret: process.env.SERVICE_SECRET, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN, audience: "https://identifier.seamlessauth.com", allowedOrigins: ["https://app.example.com"], }), @@ -375,6 +375,8 @@ This currently applies to: External delivery is a credentialed request. The adapter mints a short-lived service token from `serviceSecret`, and the auth server withholds the delivery payload if that token does not validate. `serviceSecret` must therefore match the auth server's `API_SERVICE_TOKEN` in every environment, including local development. If it does not, auth-message routes still return a success response but no message is delivered, so the adapter logs a warning whenever it requests external delivery and receives no payload back. +The auth server reads the secret from `API_SERVICE_TOKEN`, and the examples here read it in the app from `SEAMLESS_SERVICE_TOKEN`; both hold the same value. + --- ### `createSeamlessConsoleProxy(options)` @@ -660,7 +662,7 @@ options once and reuse them. const authOptions = { authServerUrl: process.env.AUTH_SERVER_URL!, cookieSecret: process.env.COOKIE_SECRET!, - serviceSecret: process.env.SERVICE_SECRET!, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN!, audience: process.env.AUTH_AUDIENCE!, }; @@ -740,7 +742,7 @@ whatever your app already uses and pass the values through as options: ```bash AUTH_SERVER_URL=http://localhost:5312 COOKIE_SECRET=local-dev-cookie-secret-at-least-32-chars -SERVICE_SECRET=local-dev-service-secret-at-least-32-chars +SEAMLESS_SERVICE_TOKEN=local-dev-service-token-at-least-32-chars ``` ```ts @@ -749,7 +751,7 @@ app.use( createSeamlessAuthServer({ authServerUrl: process.env.AUTH_SERVER_URL!, cookieSecret: process.env.COOKIE_SECRET!, - serviceSecret: process.env.SERVICE_SECRET!, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN!, audience: process.env.AUTH_SERVER_URL!, // local HTTP only, never in a deployed environment cookieSecure: false, diff --git a/packages/fastify/README.md b/packages/fastify/README.md index c85b72b..ad52766 100644 --- a/packages/fastify/README.md +++ b/packages/fastify/README.md @@ -31,7 +31,7 @@ await app.register(seamlessAuth, { authServerUrl: "https://identifier.seamlessauth.com", audience: "https://identifier.seamlessauth.com", cookieSecret: process.env.COOKIE_SECRET!, - serviceSecret: process.env.SERVICE_SECRET!, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN!, jwksKid: "2024-09-main", }); @@ -43,7 +43,9 @@ hooks scoped to those routes, so the rest of your application is untouched. `@fastify/cookie` is registered for you inside the plugin. `cookieSecret` and `serviceSecret` must be at least 32 characters and the -`serviceSecret` must match the auth API's. Both are checked at registration, so a +`serviceSecret` must match the auth API's. The auth server reads it from +`API_SERVICE_TOKEN` and the app from `SEAMLESS_SERVICE_TOKEN`, with the same value. +Both are checked at registration, so a weak secret fails at startup rather than on the first request. ## Guarding your own routes diff --git a/packages/nextjs/README.md b/packages/nextjs/README.md index 4e1c32b..a3294ea 100644 --- a/packages/nextjs/README.md +++ b/packages/nextjs/README.md @@ -31,7 +31,7 @@ export const { GET, POST, PUT, PATCH, DELETE } = createSeamlessAuthHandler({ authServerUrl: process.env.AUTH_SERVER_URL!, audience: process.env.AUTH_SERVER_URL!, cookieSecret: process.env.COOKIE_SECRET!, - serviceSecret: process.env.SERVICE_SECRET!, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN!, jwksKid: process.env.JWKS_KID, }); ``` @@ -44,7 +44,9 @@ origin: ``` `cookieSecret` and `serviceSecret` must be at least 32 characters and the -`serviceSecret` must match the auth API's. Both are checked when the handler is +`serviceSecret` must match the auth API's. The auth server reads it from +`API_SERVICE_TOKEN` and the app from `SEAMLESS_SERVICE_TOKEN`, with the same value. +Both are checked when the handler is created, so a weak secret fails at startup rather than on the first request. The adapter signs cookies with `jsonwebtoken`, so the route needs the Node.js @@ -62,7 +64,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo const session = await getSeamlessSession(await cookies(), { authServerUrl: process.env.AUTH_SERVER_URL!, cookieSecret: process.env.COOKIE_SECRET!, - serviceSecret: process.env.SERVICE_SECRET!, + serviceSecret: process.env.SEAMLESS_SERVICE_TOKEN!, jwksKid: process.env.JWKS_KID, userAgent: (await headers()).get("user-agent") ?? undefined, });