UNPKG

@nhost/nhost-js

Version:

Nhost JavaScript SDK

65 lines 2.48 kB
/** * Decodes a base64url-encoded string (RFC 4648 Section 5) to a UTF-8 string. * * JWTs use base64url encoding, which differs from standard base64 by using * `-` and `_` instead of `+` and `/`, and omitting padding. The browser's * native `atob()` does not support base64url, so we must handle the conversion. */ const decodeBase64Url = (input) => { // Convert base64url to standard base64 let base64 = input.replace(/-/g, '+').replace(/_/g, '/'); const pad = base64.length % 4; if (pad) { base64 += '='.repeat(4 - pad); } // Use TextDecoder for proper UTF-8 support (atob alone mangles multi-byte characters) const binaryString = atob(base64); const bytes = Uint8Array.from(binaryString, (c) => c.charCodeAt(0)); return new TextDecoder().decode(bytes); }; export const decodeUserSession = (accessToken) => { const s = accessToken.split('.'); if (s.length !== 3 || !s[1]) { throw new Error('Invalid access token format'); } const decodedToken = JSON.parse(decodeBase64Url(s[1])); // Convert iat and exp to Date objects const iat = typeof decodedToken['iat'] === 'number' ? decodedToken['iat'] * 1000 // Convert seconds to milliseconds : undefined; const exp = typeof decodedToken['exp'] === 'number' ? decodedToken['exp'] * 1000 // Convert seconds to milliseconds : undefined; // Process Hasura claims - dynamically convert PostgreSQL array notation to arrays const hasuraClaims = decodedToken['https://hasura.io/jwt/claims']; const processedClaims = hasuraClaims ? Object.entries(hasuraClaims).reduce((acc, [key, value]) => { if (typeof value === 'string' && isPostgresArray(value)) { acc[key] = parsePostgresArray(value); } else { acc[key] = value; } return acc; }, {}) : undefined; return { ...decodedToken, iat, exp, 'https://hasura.io/jwt/claims': processedClaims, }; }; const isPostgresArray = (value) => { return value.startsWith('{') && value.endsWith('}'); }; const parsePostgresArray = (value) => { if (!value || value === '{}') return []; // Remove curly braces and split by comma, handling quoted values return value .slice(1, -1) .split(',') .map((item) => item.trim().replace(/^"(.*)"$/, '$1')); }; //# sourceMappingURL=session.js.map