Pusat Pembangun · Luaskan platform
Halaman Terbenam — letakkan alatan anda sendiri dalam pentadbir.
Daftar halaman yang dihoskan https anda sendiri dan ia menjadi item menu yang dibenarkan di dalam pentadbir SocialHub — iframe penuh halaman yang dikotak pasir. Flash memberikan halaman anda token identiti PII yang tahan lama supaya anda boleh membenarkan pengendali, tanpa mereka log masuk semula.
Akses awal · di sebalik modul kebolehpanjangan terbuka
Cara ia berfungsi
Empat langkah dari URL anda ke item menu.
Daftar halaman anda
Pentadbir ruang kerja menambah URL https anda dalam Flash → Konfigurasi → Halaman Terbenam, dengan label menu, senarai dibenarkan asal dan peranan/peringkat yang mungkin membukanya.
Salin rahsia tandatangan
Flash menunjukkan rahsia tandatangan sekali (slotsec_…). Simpannya sebagai rahsia pelayan dalam aplikasi anda — anda mengesahkan token identiti Flash dengannya.
Flash membingkai halaman anda
Halaman ini muncul sebagai item menu bar sisi di bawah Aplikasi untuk pengendali yang dibenarkan; membukanya akan memuatkan URL anda dalam iframe berpasir dengan ?flash_context=<token> dilampirkan.
Sahkan + benarkan
Baca token, sahkannya di bahagian pelayan (HS256) dan tetapkan UI anda pada ID ruang kerja + peranan operator yang dibawanya.
Token identiti
Berumur pendek, bebas PII, ditandatangani dengan rahsia anda.
Pada setiap pemaparan, Flash menambahkan ?flash_context=<JWT> pada URL anda. Ia merupakan HS256 JWT yang ditandatangani dengan rahsia halaman anda (jadi anda — bukan platform — adalah sauh kepercayaan), sah selama paling lama 120 saat, dan ia tidak membawa data peribadi ahli — hanya id ruang kerja dan id legap pengendali + peranan kasar, jadi anda boleh memberi kebenaran.
{
"iss": "flash",
"aud": "nav.page",
"slotKey": "nav.page",
"ctx": {
"teamId": "team_...", // the workspace (tenant) — the tenant already owns this
"userId": "usr_...", // opaque operator id (NOT an email/name/phone)
"role": "org_admin", // coarse role: org_owner | org_admin | marketer | store_manager
"pageType": "nav.page",
"locale": "en"
},
"jti": "…", "iat": 1730000000, "nbf": 1730000000,
"exp": 1730000110 // <= 120s after iat
}Sahkan
Percayakan token, bukan permintaan.
Sahkan tandatangan, penerbit (flash), khalayak (nav.page) dan tarikh luput pada pelayan anda. Kemudian, benarkan pada id ruang kerja + peranan yang dibawanya — jangan sekali-kali pada kuki (iframe tidak mempunyai asal yang boleh digunakan; lihat di bawah).
// Node (jose). The secret is your page's signing secret, shown ONCE at registration.
import { jwtVerify } from "jose";
const SECRET = new TextEncoder().encode(process.env.FLASH_EMBED_SECRET); // slotsec_…
export async function verifyFlashContext(token) {
const { payload } = await jwtVerify(token, SECRET, {
algorithms: ["HS256"],
issuer: "flash",
audience: "nav.page",
requiredClaims: ["exp", "jti"],
maxTokenAge: "120s",
});
// payload.ctx = { teamId, userId, role, pageType, locale }
return payload.ctx; // → authorize the operator with this
}// In your page: read ?flash_context=… , verify it server-side, then authorize.
const token = new URLSearchParams(location.search).get("flash_context");
// POST it to YOUR backend, verify with the snippet above, and gate the UI on
// ctx.teamId + ctx.role. Never trust it unverified, and never rely on cookies —
// the iframe is a null origin (see "Framing" below).Pembingkaian & keselamatan
Apa yang mesti dilakukan oleh halaman anda.
Benarkan bingkai
Halaman anda mesti membenarkan dibingkai oleh flash.socialhub.ai — jangan hantar Pilihan-X-Frame: TOLAK; tetapkan Dasar-Keselamatan-Kandungan: frame-ancestors https://flash.socialhub.ai.
Anggapkan asal null
Flash mengosongkan iframe dengan skrip-benar dan tiada asal-benar-sama, jadi halaman anda berjalan pada asal null: tiada kuki, storan atau DOM induk Flash. Sahkan dengan token, bukan kuki.
postMessage disenaraikan dibenarkan
Hos hanya menerima postMessage daripada asal yang anda daftarkan dan hanya daripada tetingkap iframe anda. Pastikan senarai asal yang dibenarkan anda ketat dan hanya https sahaja.
Putar rahsia tandatangan daripada pengurus jika ia terdedah (token lama berhenti mengesahkan serta-merta). Halaman Terbenam ialah akses awal, dimatikan secara lalai bagi setiap ruang kerja dan mendayakannya untuk pengeluaran tertakluk kepada semakan keselamatan terbenam pihak ketiga SocialHub.
Padankan rupa pentadbir
Jadikannya terasa asli, bukan diikat.
Halaman anda memaparkan di dalam pentadbir SocialHub, jadi ia sepatutnya kelihatan seperti miliknya. Pentadbir ialah satu tema rata dan ringan yang dibina pada beberapa token — cerminkannya. Flash sudah membungkus halaman anda dalam tetingkap bertajuk dengan lencana "Pihak ketiga", jadi jangan tambah bar atas, bar sisi atau krom halaman penuh anda sendiri; hanya memberikan kandungan.
/* Starter tokens that match the SocialHub admin (flat, light, single-accent).
Drop into your embedded page so it feels native, not bolted on. */
:root {
/* type — the admin's three families */
--font-sans: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
--font-display: "Plus Jakarta Sans", "Inter", system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
/* surfaces — light theme only (the admin has no dark mode) */
--bg: #fafbfc; /* page background */
--surface: #ffffff; /* cards / panels */
--subtle: #f7fafc; /* muted fills */
--border: #e2e8f0; /* hairlines */
/* text */
--text: #121c3d; /* primary (brand navy) */
--text-2: #4a5568; /* secondary */
--muted: #64748b; /* muted */
/* accent — the admin's primary action colour */
--accent: #2ecc87;
--accent-dark: #25b678;
/* radius + 4px spacing scale + elevation */
--radius: 8px; --radius-lg: 12px;
--space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px;
--shadow-sm: 0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04);
}
body { margin: 0; background: var(--bg); color: var(--text);
font: 14px/1.5 var(--font-sans); }
h1, h2, h3 { font-family: var(--font-display); color: var(--text); }
.card { background: var(--surface); border: 1px solid var(--border);
border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
padding: var(--space-4); }
.btn { background: var(--accent); color: #fff; border: 0; font-weight: 600;
border-radius: var(--radius); padding: 8px 14px; cursor: pointer; }
.btn:hover { background: var(--accent-dark); }
code { font-family: var(--font-mono); color: var(--text-2); }Tiada krom anda sendiri
Flash menyediakan bingkai tingkap + lencana. Langkau navigasi/bar sisi/pengepala global aplikasi anda — hanya paparkan alat.
Ringan, rata, satu aksen
Tema cerah sahaja (pentadbir tiada mod gelap): kad putih pada halaman #fafbfc, sempadan #e2e8f0 yang bergaris halus, satu aksen hijau (#2ecc87).
Isi lebar, aliran tinggi
Gunakan lebar penuh dan biarkan kandungan mengalir; Hos akan menentukan saiz bingkai (kira-kira ketinggian viewport penuh) dan menatal — jangan paksa 100vh atau pengaki tetap anda sendiri.
Degradasi dengan anggun
Fon (Inter / Plus Jakarta Sans / JetBrains Mono) kembali kepada sistem-ui jika anda tidak mengehosnya sendiri; honor lebih suka gerakan-dikurangkan dan skema-warna-lebih-suka: cahaya.
Nilai-nilai ini menjejaki tema pentadbir semasa; anggap ia sebagai titik permulaan dan kekalkan jenama anda sendiri di tempat yang penting. Matlamatnya ialah halaman yang dibaca sebagai satu permukaan dengan SocialHub, bukan tetingkap ke produk yang berbeza.
Contoh lengkap
Halaman terbenam yang berfungsi dalam ~30 baris.
Pelayan Express minimum yang boleh anda jalankan dan daftarkan sebagaimana adanya: ia membolehkan Flash membingkaikannya, mengesahkan token identiti, membenarkan peranan pengendali dan memaparkan alat yang diskopkan ke ruang kerja. Salin rahsia tandatangan daripada pengurus ke dalam FLASH_EMBED_SECRET dan jalankannya.
// server.js — a complete, minimal SocialHub Embedded Page (Express + jose).
// Register https://<host>/embed in Flash → Settings → Embedded Pages, allow the
// origin https://<host>, pick roles/tier, then copy the signing secret into env.
import express from "express";
import { jwtVerify } from "jose";
const app = express();
const SECRET = new TextEncoder().encode(process.env.FLASH_EMBED_SECRET); // slotsec_…
const FLASH = "https://flash.socialhub.ai";
app.get("/embed", async (req, res) => {
// 1. Let ONLY Flash frame this page.
res.setHeader("Content-Security-Policy", "frame-ancestors " + FLASH);
// 2. Read + verify the identity token Flash appended (?flash_context=…).
let ctx;
try {
const { payload } = await jwtVerify(String(req.query.flash_context || ""), SECRET, {
algorithms: ["HS256"], issuer: "flash", audience: "nav.page",
requiredClaims: ["exp", "jti"], maxTokenAge: "120s",
});
ctx = payload.ctx; // { teamId, userId, role, pageType, locale }
} catch {
return res.status(401).send("<p>Unauthorized — open this from inside SocialHub.</p>");
}
// 3. Authorize on the VERIFIED role (never on the raw request).
const canEdit = ctx.role === "org_owner" || ctx.role === "org_admin";
// 4. Render your tool, scoped to ctx.teamId. (Values are verified + opaque;
// still escape anything user-supplied you add.)
res.send(
'<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:24px">' +
'<h1>Returns portal</h1>' +
'<p>Workspace <code>' + ctx.teamId + '</code> · operator <code>' + ctx.userId +
'</code> · role <b>' + ctx.role + '</b></p>' +
(canEdit ? '<button>Process a return</button>' : '<p>Read-only for your role.</p>') +
'</body>'
);
});
app.listen(3000, () => console.log("Embedded page on :3000/embed"));1 · Benarkan bingkai
frame-ancestors https://flash.socialhub.ai — jadi hanya pentadbir SocialHub yang boleh membingkaikannya.
2 · Sahkan token
Baca ?flash_context, sahkan HS256 + issuer flash + audience nav.page + ≤120s expiry; tolak sebaliknya.
3 · Benarkan
Ciri pintu pada peranan DISAHKAN (org_owner / org_admin / …), tidak pernah pada permintaan mentah.
4 · Paparan, skop
Paparkan alat anda untuk ctx.teamId — ruang kerja ia dibuka.
Kemudian dalam Flash → Tetapan → Halaman Terbenam: tambahkan URL (cth. https://tools.yourapp.com/embed), senaraikan asal yang sama, pilih peranan + peringkat yang mungkin membukanya dan tampal rahsia tandatangan sekali sahaja ke dalam persekitaran pelayan anda. Ia kini muncul di bawah Aplikasi untuk pengendali yang anda benarkan.