SocialHub.AI

Pusat Pengembang · Perluas platform

Halaman Tertanam — tempatkan alat Anda sendiri di admin.

Daftarkan halaman yang dihosting https Anda sendiri dan itu akan menjadi item menu yang diizinkan di dalam admin SocialHub — iframe halaman penuh yang diisolasi. Flash memberikan halaman Anda token identitas bebas PII yang berumur pendek sehingga Anda dapat mengotorisasi operator, tanpa mereka perlu masuk lagi.

Akses awal · di balik modul ekstensibilitas terbuka

Cara kerjanya

Empat langkah dari URL Anda ke item menu.

01

Daftarkan halaman Anda

Admin ruang kerja menambahkan URL https Anda di Flash → Konfigurasi → Halaman Tertanam, dengan label menu, daftar izin asal, dan peran/tingkat mana yang dapat membukanya.

02

Salin rahasia penandatanganan

Flash menampilkan rahasia penandatanganan sekali (slotsec_…). Simpan sebagai rahasia server di aplikasi Anda — Anda memverifikasi token identitas Flash dengannya.

03

Flash membingkai halaman Anda

Halaman ini muncul sebagai item menu sidebar di bawah Aplikasi untuk operator yang diizinkan; membukanya akan memuat URL Anda dalam iframe sandbox dengan ?flash_context=<token> ditambahkan.

04

Verifikasi + otorisasi

Baca token, verifikasi di sisi server (HS256), dan batasi UI Anda berdasarkan ID ruang kerja + peran operator yang dibawanya.

Token identitas

Berumur pendek, bebas PII, ditandatangani dengan rahasia Anda.

Pada setiap rendering, Flash menambahkan ?flash_context=<JWT> ke URL Anda. Ini adalah JWT HS256 yang ditandatangani dengan rahasia halaman Anda (sehingga Anda — bukan platform — adalah jangkar kepercayaan), berlaku paling lama 120 detik, dan tidak membawa data pribadi anggota — hanya ID ruang kerja dan ID buram operator + peran kasar, sehingga Anda dapat mengotorisasi.

{
  "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
}

Verifikasi

Percayai tokennya, bukan permintaannya.

Verifikasi tanda tangan, penerbit (flash), audiens (nav.page) dan masa berlaku di server Anda. Kemudian otorisasikan pada ID ruang kerja + peran yang dimilikinya — jangan pernah pada cookie (iframe tidak memiliki asal yang dapat 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 & keamanan

Apa yang harus dilakukan halaman Anda.

Izinkan kerangka kerja

Halaman Anda harus mengizinkan untuk dibingkai oleh Flash.socialhub.ai — jangan kirim X-Frame-Options: DENY; atur Content-Security-Policy: frame-ancestors https://flash.socialhub.ai.

Asumsikan asal null

Flash mengisolasi iframe dengan allow-scripts dan no allow-same-origin, sehingga halaman Anda berjalan di null origin: tanpa Flash cookie, penyimpanan, atau DOM induk. Otentikasi dengan token, bukan cookie.

postMessage diizinkan

Host hanya menerima postMessage dari origin yang Anda daftarkan, dan hanya dari jendela iframe Anda. Jaga agar daftar allowed-origins Anda tetap ketat dan hanya menggunakan https.

Ganti rahasia penandatanganan dari manajer jika pernah terekspos (token lama berhenti memverifikasi segera). Halaman Tertanam adalah akses awal, dinonaktifkan secara default per ruang kerja, dan pengaktifannya untuk produksi tunduk pada tinjauan keamanan penyematan pihak ketiga SocialHub.

Sesuaikan tampilan admin

Buat terasa alami, bukan tambahan.

Laman Anda ditampilkan di dalam admin SocialHub, sehingga akan terlihat seperti miliknya. Admin adalah satu tema datar dan ringan yang dibangun di atas beberapa token — cerminkan token tersebut. Flash sudah membungkus laman Anda di jendela berjudul dengan lencana “Pihak ketiga”, jadi jangan tambahkan bilah atas, bilah sisi, atau chrome laman penuh Anda sendiri; cukup render kontennya.

/* 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); }

Tidak ada Chrome milik Anda sendiri

Flash menyediakan bingkai jendela + lencana. Lewati navigasi/sidebar/header global aplikasi Anda — render hanya alatnya.

Ringan, datar, satu aksen

Tema terang saja (admin tidak memiliki mode gelap): kartu putih di halaman #fafbfc, border tipis #e2e8f0, satu aksen hijau (#2ecc87).

Isi lebar, alirkan tinggi

Gunakan lebar penuh dan biarkan konten mengalir; host mengatur ukuran bingkai (kira-kira setinggi viewport penuh) dan menggulir — jangan memaksakan 100vh atau footer tetap Anda sendiri.

Penurunan kualitas secara bertahap

Font (Inter / Plus Jakarta Sans / JetBrains Mono) akan kembali ke system-ui jika Anda tidak menghostingnya sendiri; hormati prefers-reduced-motion dan prefers-color-scheme: light.

Nilai-nilai ini melacak tema admin saat ini; perlakukan ini sebagai titik awal dan pertahankan merek Anda sendiri di tempat yang penting. Tujuannya adalah halaman yang terlihat sebagai satu kesatuan dengan SocialHub, bukan jendela ke produk yang berbeda.

Contoh lengkap

Halaman tersemat yang berfungsi dalam ~30 baris.

Server Express minimal yang dapat Anda jalankan dan daftarkan apa adanya: server ini memungkinkan Flash untuk membingkainya, memverifikasi token identitas, mengotorisasi peran operator, dan menampilkan alat yang dicakup ke ruang kerja. Salin rahasia penandatanganan dari manajer ke FLASH_EMBED_SECRET dan jalankan.

// 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 · Izinkan bingkai

frame-ancestors https://flash.socialhub.ai — sehingga hanya admin SocialHub yang dapat menggunakan iframe.

2 · Verifikasi token

Baca ?flash_context, verifikasi HS256 + flash penerbit + halaman navigasi audiens + masa berlaku ≤120 detik; tolak jika tidak.

3 · Otorisasi

Fitur gerbang pada peran TERVERIFIKASI (org_owner / org_admin / …), jangan pernah pada permintaan mentah.

4 · Render, terlingkup

Render alat Anda untuk ctx.teamId — ruang kerja tempat alat tersebut dibuka.

Kemudian di Flash → Pengaturan → Halaman Tertanam: tambahkan URL (misalnya https://tools.yourapp.com/embed), cantumkan asal yang sama, pilih peran + tingkatan yang dapat membukanya, dan tempelkan rahasia penandatanganan satu kali ke lingkungan server Anda. Sekarang muncul di bawah Aplikasi untuk operator yang Anda izinkan.