Skip to content

Commit 0e11c2d

Browse files
ralyodioclaude
andauthored
Use branded <dn>/… links for bid + affiliate on tenant pages (#16)
Inside a masked parked-domain iframe, the bid link was a relative /?bid=<dn>, so it navigated the iframe to moshcoding.com/?bid=<dn> — which refuses to be framed (no ?dn → CSP frame-ancestors blocks it): 'moshcoding.com refused to connect'. And the affiliate share link exposed moshcoding.com/?dn=<dn>&ref=<code>. Both now use the branded domain URL: - Bid link → https://<dn>/?bid=<dn> with target=_top (breaks out of the iframe to the branded domain instead of loading moshcoding.com in-frame) - Affiliate share link → https://<dn>/?ref=<code> - middleware also auto-allows the ?bid=<domain> as a frame-ancestor (like ?dn), so a forwarded bid page renders in-frame Note: the domain's forwarding must pass query params through (Porkbun masked forwarding with path/query, or param forwarding) for ?ref/?bid to reach the app; safeDomain already handles the appended-query case. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c7c4c58 commit 0e11c2d

3 files changed

Lines changed: 13 additions & 9 deletions

File tree

app/api/affiliate/join/route.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ export async function POST(req: NextRequest) {
3535
dn,
3636
code: aff.code,
3737
commission_pct: aff.commission_pct,
38-
// Domain-scoped share link: lands on <dn>'s page and sets the 90-day cookie.
39-
shareUrl: `${baseUrl()}/?dn=${encodeURIComponent(dn)}&ref=${encodeURIComponent(aff.code)}`,
38+
// Branded share link on the domain itself. The visit's ?ref rides through the
39+
// domain's forwarding onto ?dn=<dn>&ref=… (see safeDomain), setting the
40+
// 90-day mc_ref cookie. Requires the domain to forward query params.
41+
shareUrl: `https://${dn}/?ref=${encodeURIComponent(aff.code)}`,
4042
manageUrl: `${baseUrl()}/dashboard`,
4143
});
4244
}

components/Tenant.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export default function Tenant({ cfg }: { cfg: TenantConfig }) {
114114

115115
<AffiliateJoin dn={cfg.dn} />
116116

117-
<a className="t-bid" href={`/?bid=${encodeURIComponent(cfg.dn)}`}>💰 Bid on this domain</a>
117+
<a className="t-bid" href={`https://${cfg.dn}/?bid=${encodeURIComponent(cfg.dn)}`} target="_top" rel="noopener">💰 Bid on this domain</a>
118118

119119
{cfg.adSlot && <CrawlProofAd slot={cfg.adSlot} format={cfg.adFormat} />}
120120

middleware.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ function frameAncestors(req: NextRequest): string {
99
const allow = ["'self'", ...parked];
1010

1111
// Auto-allow the parked domain currently being rendered. A masked-forwarded
12-
// domain frames moshcoding.com/?dn=<self>, so the frame request carries its
13-
// own ?dn; trust it to iframe just its own tenant page. This means new parked
14-
// domains work without hand-editing FRAME_ANCESTORS for each one.
15-
const dn = (req.nextUrl.searchParams.get("dn") || "").trim().toLowerCase();
16-
if (dn.length <= 253 && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/.test(dn)) {
17-
allow.push(`https://${dn}`, `https://www.${dn}`);
12+
// domain frames moshcoding.com/?dn=<self> (tenant page) or ?bid=<self> (its bid
13+
// page), so the frame request carries its own domain; trust it to iframe just
14+
// its own pages. New parked domains work without hand-editing FRAME_ANCESTORS.
15+
const isDomain = (d: string) =>
16+
d.length <= 253 && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/.test(d);
17+
for (const key of ["dn", "bid"]) {
18+
const d = (req.nextUrl.searchParams.get(key) || "").trim().toLowerCase();
19+
if (isDomain(d)) allow.push(`https://${d}`, `https://www.${d}`);
1820
}
1921
return allow.join(" ");
2022
}

0 commit comments

Comments
 (0)