From 2f80b9b3b68f02632ad690a69a0446418a3d76eb Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Fri, 18 Apr 2025 12:30:07 -0400 Subject: [PATCH] fix: jwt generator (#34908) The old JWT generator code provided the anon and authenticated claims as strings. The format of this string is different from the format determined by KJUR if an object is provided (I'm guessing probably a whitespace or quote character thing, but I didn't dive down this rabbit hole.) This leads to incompatibilities when the token is used. To prevent this, the tokens are now defined as objects and KJUR's own serialization is used. --- .../components/JwtGenerator/JwtGenerator.tsx | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/apps/docs/components/JwtGenerator/JwtGenerator.tsx b/apps/docs/components/JwtGenerator/JwtGenerator.tsx index 189c466f0dd..cc767e1d5b3 100644 --- a/apps/docs/components/JwtGenerator/JwtGenerator.tsx +++ b/apps/docs/components/JwtGenerator/JwtGenerator.tsx @@ -6,23 +6,19 @@ const JWT_HEADER = { alg: 'HS256', typ: 'JWT' } const now = new Date() const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()) const fiveYears = new Date(now.getFullYear() + 5, now.getMonth(), now.getDate()) -const anonToken = ` -{ - "role": "anon", - "iss": "supabase", - "iat": ${Math.floor(today.valueOf() / 1000)}, - "exp": ${Math.floor(fiveYears.valueOf() / 1000)} -} -`.trim() -const serviceToken = ` -{ - "role": "service_role", - "iss": "supabase", - "iat": ${Math.floor(today.valueOf() / 1000)}, - "exp": ${Math.floor(fiveYears.valueOf() / 1000)} +const anonToken = { + role: 'anon', + iss: 'supabase', + iat: Math.floor(today.valueOf() / 1000), + exp: Math.floor(fiveYears.valueOf() / 1000), +} +const serviceToken = { + role: 'service_role', + iss: 'supabase', + iat: Math.floor(today.valueOf() / 1000), + exp: Math.floor(fiveYears.valueOf() / 1000), } -`.trim() const generateRandomString = (length: number) => { const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' @@ -63,12 +59,28 @@ export default function JwtGenerator({}) { const [jwtSecret, setJwtSecret] = useState(secret) const [token, setToken] = useState(anonToken) const [signedToken, setSignedToken] = useState('') + const [err, setErr] = useState(null) const handleKeySelection = (e: ChangeEvent) => { const val = e.target.value if (val == 'service') setToken(serviceToken) else setToken(anonToken) } + + const handleClaimsChange = (e: ChangeEvent) => { + try { + const newTok = JSON.parse(e.target.value) + setToken(newTok) + setErr(null) + } catch (err) { + const errMessage = + !!err && typeof err === 'object' && 'message' in err && typeof err.message === 'string' + ? err.message + : '' + setErr('Not a valid JSON body' + (errMessage ? `: ${errMessage}` : '')) + } + } + const generate = () => { const signedJWT = KJUR.jws.JWS.sign(null, JWT_HEADER, token, jwtSecret) setSignedToken(signedJWT) @@ -102,10 +114,13 @@ export default function JwtGenerator({}) { type="text" rows={6} placeholder="A valid JWT Token" - value={token} + defaultValue={JSON.stringify(token, null, 2)} style={{ fontFamily: 'monospace' }} - onChange={(e) => setToken(e.target.value)} + onChange={handleClaimsChange} /> + {err && ( + Input must be valid JSON. {err} + )}