@@ -24,6 +24,7 @@ const JWT_HMAC_ALGOS = ['HS256', 'HS384', 'HS512']
2424const JWT_RSA_ALGOS = [ 'RS256' , 'RS384' , 'RS512' ]
2525const JWT_ECC_ALGOS = [ 'ES256' , 'ES384' , 'ES512' ]
2626const JWT_ED_ALGOS = [ 'EdDSA' ]
27+ export const MAX_NUMERIC_JWT_EXPIRATION = Number . MAX_SAFE_INTEGER
2728
2829export type SignedToken = {
2930 url : string
@@ -231,8 +232,12 @@ export async function signJWT(
231232) : Promise < string > {
232233 const signer = new SignJWT ( payload ) . setIssuedAt ( )
233234 if ( expiresIn ) {
234- const expiresInStr = typeof expiresIn === 'string' ? expiresIn : Math . floor ( expiresIn ) + 's'
235- signer . setExpirationTime ( expiresInStr )
235+ const expiresInStr = getJWTExpirationTime ( expiresIn )
236+ try {
237+ signer . setExpirationTime ( expiresInStr )
238+ } catch ( e ) {
239+ throw ERRORS . InvalidParameter ( 'expiresIn' , { error : e as Error } )
240+ }
236241 }
237242
238243 if ( typeof secret === 'string' ) {
@@ -246,6 +251,24 @@ export async function signJWT(
246251 }
247252}
248253
254+ function getJWTExpirationTime ( expiresIn : string | number ) {
255+ if ( typeof expiresIn === 'string' ) {
256+ return expiresIn
257+ }
258+
259+ if ( ! Number . isFinite ( expiresIn ) ) {
260+ throw ERRORS . InvalidParameter ( 'expiresIn' )
261+ }
262+
263+ const expiresInSeconds = Math . floor ( expiresIn )
264+
265+ if ( ! Number . isSafeInteger ( expiresInSeconds ) || expiresInSeconds > MAX_NUMERIC_JWT_EXPIRATION ) {
266+ throw ERRORS . InvalidParameter ( 'expiresIn' )
267+ }
268+
269+ return `${ expiresInSeconds } s`
270+ }
271+
249272/**
250273 * Generate a new random HS512 JWK that can be used for signing JWTs
251274 */
0 commit comments