← Queen of San Diego — Tech Blog
2026-06-20

Debugging Magic-Link Routing and Wiring Crew SSO Across Personal Charter Pages

When the Magic Link Stops Being Magic

The Queen of San Diego runs personalized charter pages — subdomains like darrell.queenofsandiego.com — where guests and crew authenticate via a short magic token in the query string (?m=ARN52HJX). On June 20th, one of those pages went dark. Navigating to the URL returned nothing — not a 404, not an error page, just silence. That was the entry point for a debugging session that touched the auth token pipeline, the guest photo upload flow, and eventually the crew portal's single sign-on story.

Tracing the Broken Magic Link

The ?m= token is looked up in a DynamoDB table that maps short codes to charter slugs and access levels. The page itself is a CloudFront distribution backed by an S3-hosted static site, with a small Lambda@Edge function that intercepts the request, validates the token, and either lets the request through or redirects to an error page.

The failure mode here was subtle: the Lambda wasn't crashing — it was silently swallowing the request because a config value pointed at the wrong DynamoDB table region. The token lookup returned nothing, and instead of redirecting to an error, the function fell through to a code path that returned an empty 200. The fix was a one-line correction to the table endpoint in the Lambda environment, redeployed and propagated via CloudFront invalidation.

The harder question was whether the fix would generalize. The answer, after checking the other active personalized subdomains, was yes — they all shared the same Lambda function via a single CloudFront behavior, so the single fix covered all of them.

Reconnecting the Photo Upload Flow

Separate from the broken link, the session surfaced a workflow gap in the new charter provisioning path. JADA has an existing guest photo upload system where each charter gets a unique upload code that's emailed directly to guests — no approval gate, no login required. Guests land on an upload page, enter their code, and photos go straight to an S3 bucket under a per-charter prefix.

The problem was that the new charter flow being built wasn't generating or emailing that code. The code generation logic existed in an older provisioning script but hadn't been ported forward. The fix involved:

The photo upload flow is intentionally gate-free because the friction of asking guests to create accounts kills participation. The code acts as a lightweight capability token — if you have it, you can upload.

Crew Portal SSO: Don't Make Authenticated Crew Log In Twice

The crew-facing side of the stack has a similar structure: each crew member has a personal page (firstname.queenofsandiego.com) they access via their own magic link, plus a shared Crew Portal they can navigate to from that page. The bug report was clear: clicking "Open Crew Portal" from an already-authenticated personal page was dropping crew back at a login prompt.

The fix was a token passthrough pattern. When crew authenticates to their personal page, the session token is stored in sessionStorage. The "Open Crew Portal" button was updated to append that token as a query parameter when navigating to the portal URL. The portal's Lambda@Edge function was already capable of accepting a token via query string — it just wasn't being sent.

// Before: hard link
href="https://crew.queenofsandiego.com"

// After: token passthrough
const tok = sessionStorage.getItem('crew_token');
href = `https://crew.queenofsandiego.com${tok ? '?m=' + tok : ''}`;

This avoids building a full OAuth or session-sharing infrastructure while still giving crew a smooth experience. The tradeoff is that the token appears in the URL momentarily, but it's the same token they already navigated in on, so the exposure surface doesn't change.

What This Session Added Up To

Three independent-looking bugs shared a root cause: the personalized-page auth stack was built incrementally and new flows weren't inheriting the pieces that already worked. The photo code, the magic link validator, and the crew token passthrough all existed — they just needed to be wired into the current provisioning and navigation paths. The session was mostly archaeology and reconnection, not new invention.