import { useEffect, useState } from 'react'; import { Badge, Box, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Separator, Stack, Text } from '@jtl-software/platform-ui-react'; import { ShieldCheck } from 'lucide-react'; import { fetchUserInfo, useJtlAuth } from '@jtl-software/cloud-apps-auth'; const issuer = import.meta.env.VITE_JTL_ISSUER ?? ''; // `npm run register` sets this when a node backend is present; the backend-verify demo stays hidden otherwise. const backendUrl = import.meta.env.VITE_BACKEND_URL; /** Pretty-printed JSON in a scrollable box, for token claims and API responses. */ const JsonBlock: React.FC<{ value: unknown }> = ({ value }) => (
{JSON.stringify(value, null, 2)}
); /** Example page showing how to read the signed-in user from the token: id-token claims, the access * token, and the /userinfo response. Reached only behind RequireJtlAuth, so a user exists. */ const UserExamplePage: React.FC = () => { const { user } = useJtlAuth(); const accessToken = user?.access_token; const [userInfo, setUserInfo] = useState | null>(null); const [userInfoError, setUserInfoError] = useState(null); const [verifyResult, setVerifyResult] = useState(null); const [verifying, setVerifying] = useState(false); useEffect(() => { if (!accessToken || !issuer) return; let cancelled = false; // Reset both so a later success can't keep showing a stale error, and vice versa. setUserInfo(null); setUserInfoError(null); fetchUserInfo(issuer, accessToken) .then(info => !cancelled && setUserInfo(info)) .catch(err => !cancelled && setUserInfoError(err instanceof Error ? err.message : String(err))); return () => { cancelled = true; }; }, [accessToken]); if (!user) return null; const { profile } = user; // Send the access token to the backend, which verifies it against the JTL IdP and returns the claims. const verifyInBackend = async () => { if (!accessToken || !backendUrl) return; setVerifying(true); setVerifyResult(null); try { const res = await fetch(`${backendUrl}/verify-token`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}` }, }); setVerifyResult(await res.json()); } catch (err) { setVerifyResult({ error: err instanceof Error ? err.message : String(err) }); } finally { setVerifying(false); } }; return ( Signed in {profile.name ?? profile.email ?? profile.sub ?? 'Authenticated user'} ID TOKEN CLAIMS {profile.email && ( {profile.email} )} {profile.sub && ( {profile.sub} )} ACCESS TOKEN {accessToken} USERINFO {userInfoError ? ( {userInfoError} ) : userInfo ? ( ) : ( Loading… )} {backendUrl && ( <> BACKEND VERIFICATION Sends the access token to your backend, which verifies its signature and issuer against the JTL IdP.