@nhost/nhost-js
Version:
Nhost JavaScript SDK
65 lines • 2.48 kB
JavaScript
/**
* 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