User verification ensures that only authorized users can access your private roadmaps or widgets. Because this process involves sensitive credentials (your Shared Secret), the authentication token must be generated on your server, never in the browser.
NextJS demo
Section titled “NextJS demo”You can find an examxple implementation of the user verfiication flow in NextJS on Github.
View on GithubExpress server demo
Section titled “Express server demo”Prerequisites
Section titled “Prerequisites”Before running the example, ensure you have the following:
- Node.js installed (v18 or newer recommended).
- Your Hub credentials (found in Settings → User Verification):
ACCOUNT_IDSHARED_SECRET
- The Channel ID for the portal you want to embed finding-the-channel-id.md
CHANNEL_ID
Implementation
Section titled “Implementation”Set up the project
Section titled “Set up the project”Open your terminal and run the following commands to create a folder and install the necessary web server framework (
express).Terminal window mkdir released-auth-democd released-auth-demonpm init -ynpm install expressCreate the server file
Section titled “Create the server file”Create a file named
server.jsand paste in the code below.const express = require('express');const app = express();const port = 3000;// --- CONFIGURATION ---// TODO: Replace with your actual values from Hub Settingsconst CONFIG = {SHARED_SECRET: 'YOUR_SHARED_SECRET',ACCOUNT_ID: 'YOUR_ACCOUNT_ID',CHANNEL_ID: 'YOUR_CHANNEL_ID'};// --- MOCK USER DATA ---// In your real app, this comes from your database or sessionconst currentUser = {id: "user_12345",email: "john.doe@example.com",name: "John Doe",avatar: "https://ui-avatars.com/api/?name=John+Doe"};// --- THE ROUTE ---app.get('/', async (req, res) => {try {// 1. Generate the Auth Token server-side// We send the current user's details to Hub to get a temporary tokenconst response = await fetch("https://accounts.releasedhub.com/auth/api/impersonation/token", {method: "POST",headers: {"Content-Type": "application/json","Authorization": `Bearer ${CONFIG.SHARED_SECRET}`},body: JSON.stringify({account_id: CONFIG.ACCOUNT_ID,user_id: currentUser.id,user_email: currentUser.email,profile: {name: currentUser.name,avatar_url: currentUser.avatar}}),});if (!response.ok) throw new Error(`API Error: ${response.statusText}`);const data = await response.json();const token = data; // The short-lived JWT// 2. Serve the HTML with the token injectedres.send(`<!DOCTYPE html><html><head><title>Hub Verification Example</title><script type="module" src="https://embed.released.so/released-embed.js"></script></head><body style="font-family: sans-serif; padding: 40px;"><h1>Hello, ${currentUser.name}</h1><p>This roadmap is authenticated specifically for you.</p><hr /><released-pagechannel-id="${CONFIG.CHANNEL_ID}"auth-token="${token}"></released-page></body></html>`);} catch (error) {console.error(error);res.status(500).send("Error generating token. Check server console.");}});app.listen(port, () => {console.log(`Server running at http://localhost:${port}`);});Run the server
Section titled “Run the server”Start the application in your terminal:
Bash
node server.jsTunneling (Required for HTTPS)
Section titled “Tunneling (Required for HTTPS)”Most browsers restrict embedded widgets or cookies when running on
localhost. To test this properly, you need a publichttpsURL. We recommend using a tool like ngrok.-
Install ngrok (if you haven’t already).
-
Run the tunnel in a new terminal window:
Bash
ngrok http 3000 -
Copy the Forwarding URL provided by ngrok (e.g.,
https://a1b2-c3d4.ngrok-free.dev). -
Important: Add this URL to your Allowed Domains in the Hub dashboard if you have domain restrictions enabled.
-
Open the URL in your browser to see your authenticated roadmap.
-
Whitelist the ngrok domain
Section titled “Whitelist the ngrok domain”Add the ngrok domain to your list of trusted domains for embedded content.
Troubleshooting
Section titled “Troubleshooting”Widget not loading?
Check your browser console. If you see CORS errors, ensure your ngrok URL is added to the “Allowed Domains” list in your Hub settings.
Fetch is not defined?
If you are on an older version of Node.js (< v18), upgrade Node or install node-fetch.
401 Unauthorized?
- Double-check that your SHARED_SECRET was copied correctly and contains no extra spaces.
- Check the html source and ensure the token property in the embed html element was successfully populated.