From d780ad64500b8a9901a0c1e845a6b72b3f521860 Mon Sep 17 00:00:00 2001 From: Prathamesh Gujar Date: Sun, 28 Jun 2026 18:26:06 +0530 Subject: [PATCH 1/3] docs: add HTTP signed cookies server example --- .../scripts/http_server_signed_cookies.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 examples/scripts/http_server_signed_cookies.ts diff --git a/examples/scripts/http_server_signed_cookies.ts b/examples/scripts/http_server_signed_cookies.ts new file mode 100644 index 000000000..d288ec510 --- /dev/null +++ b/examples/scripts/http_server_signed_cookies.ts @@ -0,0 +1,78 @@ +/** + * @title HTTP server: Signed Cookies + * @difficulty intermediate + * @tags http, server, web-crypto + * @resource {https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies} MDN: Using HTTP cookies + * @resource {/examples/http_server_cookies} Example: HTTP server: Cookies + * @group Network + * + * Securely sign and verify browser cookies using native cryptographic utilities + * to prevent client-side tampering. While clients can see the values of signed + * cookies, they cannot manipulate them without invalidating the cryptographic signature. + */ + +import { + getSignedCookie, + setSignedCookie, +} from "jsr:@std/http/unstable-signed-cookie"; + +// Cryptographic keys must be generated using web standard Web Crypto APIs. +const cryptoKey = await crypto.subtle.generateKey( + { name: "HMAC", hash: "SHA-256" }, + true, + ["sign", "verify"], +); + +Deno.serve(async (req) => { + const { pathname } = new URL(req.url); + + // ROUTE 1: Setting a secure, signed session cookie. + if (pathname === "/set") { + const res = new Response( + "A cryptographically signed cookie has been successfully set!\n", + ); + + // Pass parameters: headers, cookie name, value, secret key, and option flags. + await setSignedCookie(res.headers, "session_id", "user_abc123", cryptoKey, { + path: "/", + httpOnly: true, + }); + + return res; + } + + // ROUTE 2: Fetching and verifying the incoming signed cookie. + if (pathname === "/get") { + // getSignedCookie extracts the cookie and evaluates the signature against our key. + const cookieValue = await getSignedCookie( + req.headers, + "session_id", + cryptoKey, + ); + + // If the client tampered with the string value, verification fails and returns undefined. + if (cookieValue === undefined) { + return new Response( + "Unauthorized: Cookie is missing or signature verification failed!\n", + { + status: 401, + }, + ); + } + + return new Response( + `Access Granted. Verified Session Data: ${cookieValue}\n`, + ); + } + + return new Response("not found\n", { status: 404 }); +}); + +// The full flow with curl, using a cookie jar (-c saves cookies, -b sends +// them back): +// +// curl -s -c /tmp/jar http://localhost:8000/set +// A cryptographically signed cookie has been successfully set! +// +// curl -s -b /tmp/jar http://localhost:8000/get +// Access Granted. Verified Session Data: user_abc123 From 7449d62671ff1d631fd30187730ebb33fd28515a Mon Sep 17 00:00:00 2001 From: Prathamesh Gujar Date: Sun, 28 Jun 2026 22:56:58 +0530 Subject: [PATCH 2/3] Pipeline fix --- .../scripts/http_server_signed_cookies.ts | 47 +++++-------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/examples/scripts/http_server_signed_cookies.ts b/examples/scripts/http_server_signed_cookies.ts index d288ec510..76202945b 100644 --- a/examples/scripts/http_server_signed_cookies.ts +++ b/examples/scripts/http_server_signed_cookies.ts @@ -1,20 +1,17 @@ /** * @title HTTP server: Signed Cookies * @difficulty intermediate - * @tags http, server, web-crypto + * @tags cli, deploy * @resource {https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies} MDN: Using HTTP cookies * @resource {/examples/http_server_cookies} Example: HTTP server: Cookies * @group Network * - * Securely sign and verify browser cookies using native cryptographic utilities - * to prevent client-side tampering. While clients can see the values of signed + * Securely sign and verify browser cookies using native cryptographic utilities + * to prevent client-side tampering. While clients can see the values of signed * cookies, they cannot manipulate them without invalidating the cryptographic signature. */ -import { - getSignedCookie, - setSignedCookie, -} from "jsr:@std/http/unstable-signed-cookie"; +import { getSignedCookie, setSignedCookie } from "jsr:@std/http/unstable-signed-cookie"; // Cryptographic keys must be generated using web standard Web Crypto APIs. const cryptoKey = await crypto.subtle.generateKey( @@ -28,9 +25,7 @@ Deno.serve(async (req) => { // ROUTE 1: Setting a secure, signed session cookie. if (pathname === "/set") { - const res = new Response( - "A cryptographically signed cookie has been successfully set!\n", - ); + const res = new Response("A cryptographically signed cookie has been successfully set!\n"); // Pass parameters: headers, cookie name, value, secret key, and option flags. await setSignedCookie(res.headers, "session_id", "user_abc123", cryptoKey, { @@ -43,36 +38,16 @@ Deno.serve(async (req) => { // ROUTE 2: Fetching and verifying the incoming signed cookie. if (pathname === "/get") { - // getSignedCookie extracts the cookie and evaluates the signature against our key. - const cookieValue = await getSignedCookie( - req.headers, - "session_id", - cryptoKey, - ); + const cookieValue = await getSignedCookie(req.headers, "session_id", cryptoKey); - // If the client tampered with the string value, verification fails and returns undefined. if (cookieValue === undefined) { - return new Response( - "Unauthorized: Cookie is missing or signature verification failed!\n", - { - status: 401, - }, - ); + return new Response("Unauthorized: Cookie is missing or signature verification failed!\n", { + status: 401, + }); } - return new Response( - `Access Granted. Verified Session Data: ${cookieValue}\n`, - ); + return new Response(`Access Granted. Verified Session Data: ${cookieValue}\n`); } return new Response("not found\n", { status: 404 }); -}); - -// The full flow with curl, using a cookie jar (-c saves cookies, -b sends -// them back): -// -// curl -s -c /tmp/jar http://localhost:8000/set -// A cryptographically signed cookie has been successfully set! -// -// curl -s -b /tmp/jar http://localhost:8000/get -// Access Granted. Verified Session Data: user_abc123 +}); \ No newline at end of file From d37ab932eabf671de236d6d0c7a4a84bff08f7a3 Mon Sep 17 00:00:00 2001 From: Prathamesh Gujar Date: Sun, 28 Jun 2026 23:43:28 +0530 Subject: [PATCH 3/3] Formatting fix --- .../scripts/http_server_signed_cookies.ts | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/examples/scripts/http_server_signed_cookies.ts b/examples/scripts/http_server_signed_cookies.ts index 76202945b..291b374d7 100644 --- a/examples/scripts/http_server_signed_cookies.ts +++ b/examples/scripts/http_server_signed_cookies.ts @@ -6,12 +6,15 @@ * @resource {/examples/http_server_cookies} Example: HTTP server: Cookies * @group Network * - * Securely sign and verify browser cookies using native cryptographic utilities - * to prevent client-side tampering. While clients can see the values of signed + * Securely sign and verify browser cookies using native cryptographic utilities + * to prevent client-side tampering. While clients can see the values of signed * cookies, they cannot manipulate them without invalidating the cryptographic signature. */ -import { getSignedCookie, setSignedCookie } from "jsr:@std/http/unstable-signed-cookie"; +import { + getSignedCookie, + setSignedCookie, +} from "jsr:@std/http/unstable-signed-cookie"; // Cryptographic keys must be generated using web standard Web Crypto APIs. const cryptoKey = await crypto.subtle.generateKey( @@ -25,7 +28,9 @@ Deno.serve(async (req) => { // ROUTE 1: Setting a secure, signed session cookie. if (pathname === "/set") { - const res = new Response("A cryptographically signed cookie has been successfully set!\n"); + const res = new Response( + "A cryptographically signed cookie has been successfully set!\n", + ); // Pass parameters: headers, cookie name, value, secret key, and option flags. await setSignedCookie(res.headers, "session_id", "user_abc123", cryptoKey, { @@ -38,16 +43,25 @@ Deno.serve(async (req) => { // ROUTE 2: Fetching and verifying the incoming signed cookie. if (pathname === "/get") { - const cookieValue = await getSignedCookie(req.headers, "session_id", cryptoKey); + const cookieValue = await getSignedCookie( + req.headers, + "session_id", + cryptoKey, + ); if (cookieValue === undefined) { - return new Response("Unauthorized: Cookie is missing or signature verification failed!\n", { - status: 401, - }); + return new Response( + "Unauthorized: Cookie is missing or signature verification failed!\n", + { + status: 401, + }, + ); } - return new Response(`Access Granted. Verified Session Data: ${cookieValue}\n`); + return new Response( + `Access Granted. Verified Session Data: ${cookieValue}\n`, + ); } return new Response("not found\n", { status: 404 }); -}); \ No newline at end of file +});