Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion samples/browser/quickstart/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
VITE_THUNDERID_CLIENT_ID=your-client-id-here
# Base URL of your ThunderID deployment (org tenant).
VITE_THUNDERID_BASE_URL=https://localhost:8090

# OAuth2 Client ID for this app. ThunderID Console -> your application -> Overview.
VITE_THUNDERID_CLIENT_ID=your-client-id-here
2 changes: 1 addition & 1 deletion samples/browser/quickstart/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ThunderID Browser Quickstart

[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/fork/github/thunder-id/javascript-sdks/tree/main/samples/browser/quickstart?file=.env&terminal=dev)
<a href="https://stackblitz.com/fork/github/thunder-id/javascript-sdks/tree/main/samples/browser/quickstart?file=.env&terminal=dev" target="_blank"><img src="https://developer.stackblitz.com/img/open_in_stackblitz.svg" alt="Open in StackBlitz" /></a>

A minimal Vite + vanilla JS app demonstrating sign-in and sign-out with the ThunderID JavaScript SDK (`@thunderid/browser`).

Expand Down
7 changes: 6 additions & 1 deletion samples/browser/quickstart/scripts/prepare-dev.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ const root = path.join(__dirname, '..');
const envExample = path.join(root, '.env.example');
const envTarget = path.join(root, '.env');
if (fs.existsSync(envExample) && !fs.existsSync(envTarget)) {
fs.copyFileSync(envExample, envTarget);
// Blank placeholder values (e.g. `your-client-id-here`) so the copied .env
// still trips the app's missing-env-var check until real values are filled in.
const envContent = fs
.readFileSync(envExample, 'utf8')
.replace(/^([A-Z0-9_]+)=(your-\S*|generate-with-\S*)$/gm, '$1=');
fs.writeFileSync(envTarget, envContent);
}

const pkgPath = path.join(root, 'package.json');
Expand Down
3 changes: 2 additions & 1 deletion samples/browser/quickstart/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import './style.css'
import auth, { missingEnvVars } from './auth.js'
import { renderSignedOutNav, renderSignedInNav, attachNavHandlers, attachSignedOutNavHandlers } from './components/nav.js'
import { renderProfileDialog, attachProfileDialogHandlers } from './components/profileDialog.js'
import { renderSignedOut, renderHome, renderConfigNeeded, startCountdown, attachSignedOutHandlers } from './pages/home.js'
import { renderSignedOut, renderHome, renderConfigNeeded, startCountdown, attachSignedOutHandlers, attachConfigNeededHandlers } from './pages/home.js'
import { renderTokenDebug, attachTokenHandlers } from './pages/token.js'

let isDark = false
Expand Down Expand Up @@ -68,6 +68,7 @@ async function renderApp() {
if (missingEnvVars.length > 0) {
app.innerHTML = renderSignedOutNav({ isDark, hideSignIn: true }) + renderConfigNeeded(missingEnvVars)
attachSignedOutNavHandlers({ auth })
attachConfigNeededHandlers()
return
}

Expand Down
86 changes: 78 additions & 8 deletions samples/browser/quickstart/src/pages/home.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ export function attachSignedOutHandlers({ auth }) {
}

export function renderConfigNeeded(missing) {
const origin = typeof window !== 'undefined' ? window.location.origin : ''

return `
<section class="hero">
<div class="hero-inner">
Expand All @@ -150,20 +152,88 @@ export function renderConfigNeeded(missing) {
</div>
<h1 class="hero-title">Configuration needed</h1>
<p class="hero-subtitle">
This quickstart can't reach ThunderID yet. Set the following
environment variable(s), then restart the dev server.
This quickstart can't reach ThunderID yet. Follow the steps below,
then restart the dev server.
</p>
<ul class="config-list">
${missing.map(key => `<li class="config-list-item">${escapeHtml(key)}</li>`).join('')}
</ul>
<p class="config-hint">
Copy <code>.env.example</code> to <code>.env.local</code>, fill in the
values from your ThunderID application, then run <code>npm run dev</code> again.

<div class="config-step">
<div class="config-step-label">Step 1 &middot; Set environment variables</div>
<ul class="config-list">
${missing.map(key => `<li class="config-list-item">${escapeHtml(key)}</li>`).join('')}
</ul>
<p class="config-hint">
Copy <code>.env.example</code> to <code>.env</code>, fill in the
values from your ThunderID application, then run <code>npm run dev</code> again.
</p>
</div>

<div class="config-step">
<div class="config-step-label">Step 2 &middot; Allow this origin for CORS</div>
<div class="config-box">
<p class="config-box-body">
Sign-in requests from this origin will be blocked by the browser
until it's added to your ThunderID deployment's allowed CORS
origins. In the <strong>ThunderID Console</strong>, go to
<strong> Settings &rarr; CORS &rarr; Allowed origins</strong> and
add it.
</p>
<div class="config-value-row">
<code class="config-value">${escapeHtml(origin)}</code>
<button class="token-copy-btn config-copy-btn" data-copy="${escapeHtml(origin)}">Copy</button>
</div>
</div>
</div>

<div class="config-step">
<div class="config-step-label">Step 3 &middot; Register redirect URIs</div>
<div class="config-box">
<p class="config-box-body">
This origin also doubles as this app's Authorized redirect URI
and Post-Logout Redirect URI. In the <strong>ThunderID
Console</strong>, open this application and go to
<strong> Advanced Settings &rarr; OAuth2 Configuration</strong>,
then add it to both fields below.
</p>
<div class="config-value-group">
<div>
<div class="config-value-label">Authorized redirect URI</div>
<div class="config-value-row">
<code class="config-value">${escapeHtml(origin)}</code>
<button class="token-copy-btn config-copy-btn" data-copy="${escapeHtml(origin)}">Copy</button>
</div>
</div>
<div>
<div class="config-value-label">Post-Logout Redirect URI</div>
<div class="config-value-row">
<code class="config-value">${escapeHtml(origin)}</code>
<button class="token-copy-btn config-copy-btn" data-copy="${escapeHtml(origin)}">Copy</button>
</div>
</div>
</div>
</div>
</div>

<p class="config-docs-note">
Need more info? Take a look at the
<a href="https://thunderid.dev/docs/next/getting-started/connect-your-application/browser/" target="_blank" rel="noopener noreferrer">Browser quickstart guide.</a>
</p>
</div>
</section>`
}

export function attachConfigNeededHandlers() {
if (!navigator.clipboard) return
document.querySelectorAll('.config-copy-btn').forEach((btn) => {
btn.addEventListener('click', () => {
navigator.clipboard.writeText(btn.getAttribute('data-copy') || '').then(() => {
const original = btn.textContent
btn.textContent = 'Copied!'
setTimeout(() => { btn.textContent = original }, 1500)
})
})
})
}

export function renderHome({ user, idToken }) {
const now = Math.floor(Date.now() / 1000)
const givenName = user?.given_name || user?.name || user?.username || 'there'
Expand Down
83 changes: 83 additions & 0 deletions samples/browser/quickstart/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,89 @@ body {
font-size: 13px;
}

.config-step {
width: 100%;
max-width: 420px;
margin: 0 auto 28px;
}

.config-step-label {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.09em;
color: var(--muted);
margin-bottom: 10px;
text-align: left;
}

.config-step .config-list,
.config-step .config-hint {
margin-left: 0;
margin-right: 0;
}

.config-box {
text-align: left;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 16px;
}

.config-box-body {
font-size: 13px;
color: var(--muted);
line-height: 1.6;
margin-bottom: 14px;
}

.config-value-row {
display: flex;
align-items: center;
gap: 8px;
}

.config-value {
flex: 1;
min-width: 0;
overflow-x: auto;
white-space: nowrap;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 12px;
color: var(--text);
background: var(--blue-subtle);
border-radius: 4px;
padding: 8px 10px;
}

.config-value-label {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--muted);
margin-bottom: 4px;
}

.config-value-group {
display: flex;
flex-direction: column;
gap: 12px;
}

.config-docs-note {
font-size: 13px;
color: var(--muted);
max-width: 420px;
margin: 0 auto;
}

.config-docs-note a {
color: var(--blue);
font-weight: 600;
}

/* Buttons */
.btn-primary,
.btn-outline,
Expand Down
8 changes: 7 additions & 1 deletion samples/express/quickstart/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Base URL of your ThunderID deployment (org tenant).
THUNDERID_BASE_URL=https://localhost:8090

# OAuth2 Client ID for this app. ThunderID Console -> your application -> Overview.
THUNDERID_CLIENT_ID=your-client-id-here
# OAuth2 Client Secret for this app. Shown once when the application is created;
# if lost, regenerate it from the app's Credentials tab (under Edit). Server-only, never expose to the browser.
THUNDERID_CLIENT_SECRET=your-client-secret-here
THUNDERID_BASE_URL=https://localhost:8090

# DANGER: Disables ALL TLS verification. Only for local development with self-signed certs. NEVER use in production.
NODE_TLS_REJECT_UNAUTHORIZED=0
2 changes: 1 addition & 1 deletion samples/express/quickstart/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ThunderID Express Quickstart

[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/fork/github/thunder-id/javascript-sdks/tree/main/samples/express/quickstart?file=.env&terminal=dev)
<a href="https://stackblitz.com/fork/github/thunder-id/javascript-sdks/tree/main/samples/express/quickstart?file=.env&terminal=dev" target="_blank"><img src="https://developer.stackblitz.com/img/open_in_stackblitz.svg" alt="Open in StackBlitz" /></a>

A minimal Express.js **API** protected by ThunderID access tokens, using the ThunderID JavaScript
SDK (`@thunderid/express`). Unlike the browser-focused quickstarts, this sample doesn't have a
Expand Down
40 changes: 33 additions & 7 deletions samples/express/quickstart/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,39 @@ function renderConfigNeeded() {
<div class="hero-mark">${thunderMark(40)}</div>
<div class="hero-badge config-badge"><span class="hero-badge-line"></span><span>Setup required</span><span class="hero-badge-line"></span></div>
<h1 class="hero-title">Configuration needed</h1>
<p class="hero-subtitle">This quickstart can't reach ThunderID yet. Set the following environment
variable(s), then restart the server.</p>
<ul class="config-list">
${missingEnvVars.map((key) => `<li class="config-list-item">${esc(key)}</li>`).join('')}
</ul>
<p class="config-hint">Copy <code>.env.example</code> to <code>.env</code>, fill in the values from
your ThunderID application, then run <code>npm run dev</code> again.</p>
<p class="hero-subtitle">This quickstart can't reach ThunderID yet. Follow the steps below, then
restart the server.</p>

<div class="config-step">
<div class="config-step-label">Step 1 &middot; Set environment variables</div>
<ul class="config-list">
${missingEnvVars.map((key) => `<li class="config-list-item">${esc(key)}</li>`).join('')}
</ul>
<p class="config-hint">Copy <code>.env.example</code> to <code>.env</code>, fill in the values from
your ThunderID application, then run <code>npm run dev</code> again.</p>
</div>

<div class="config-step">
<div class="config-step-label">Step 2 &middot; Register redirect URIs</div>
<div class="config-box">
<p class="config-box-body">Sign-in and sign-out are handled by this app's server, so no CORS
configuration is needed. In the <strong>ThunderID Console</strong>, open this application and go to
<strong> Advanced Settings &rarr; OAuth2 Configuration</strong>, then add the exact URIs below.</p>
<div class="config-value-group">
<div>
<div class="config-value-label">Authorized redirect URI</div>
<code class="config-value">http://localhost:3000/login</code>
</div>
<div>
<div class="config-value-label">Post-Logout Redirect URI</div>
<code class="config-value">http://localhost:3000/logout</code>
</div>
</div>
</div>
</div>

<p class="config-docs-note">Need more info? Take a look at the
<a href="https://thunderid.dev/docs/next/getting-started/connect-your-application/express/" target="_blank" rel="noopener noreferrer">Express quickstart guide.</a></p>
</div>
</section>`,
});
Expand Down
76 changes: 76 additions & 0 deletions samples/express/quickstart/public/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,82 @@ button {
font-size: 13px;
}

.config-step {
width: 100%;
max-width: 420px;
margin: 0 auto 28px;
}

.config-step-label {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.09em;
color: var(--color-muted);
margin-bottom: 10px;
text-align: left;
}

.config-step .config-list,
.config-step .config-hint {
margin-left: 0;
margin-right: 0;
}

.config-box {
text-align: left;
background: var(--color-card);
border: 1px solid var(--color-border);
border-radius: var(--radius-card);
padding: 16px;
}

.config-box-body {
font-size: 13px;
color: var(--color-muted);
line-height: 1.6;
margin-bottom: 14px;
}

.config-value-group {
display: flex;
flex-direction: column;
gap: 12px;
}

.config-value-label {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--color-muted);
margin-bottom: 4px;
}

.config-value {
display: block;
overflow-x: auto;
white-space: nowrap;
font-family: var(--font-mono);
font-size: 12px;
color: var(--color-text);
background: rgba(54, 136, 255, 0.08);
border-radius: 4px;
padding: 8px 10px;
}

.config-docs-note {
font-size: 13px;
color: var(--color-muted);
max-width: 420px;
margin: 0 auto;
}

.config-docs-note a {
color: var(--color-primary);
font-weight: 600;
}

/* ── Token debug page ── */
.token-header {
display: flex;
Expand Down
Loading
Loading