import { Buffer } from 'buffer' ; import { URL } from 'url' ; import * as crypto from 'crypto' ; import type { TUtils , TB64UrlEncode , TIsVerified , IPayload } from './index.d' ; const atob = ( a = '' ) => Buffer . from ( a , 'base64' ) . toString ( 'binary' ) ; const base64UrlEncode = ( buffer ) => buffer . toString ( 'base64' ) . replace ( /\+/g , '-' ) . replace ( /\//g , '_' ) . replace ( /=+$/g , '' ) ; const isVerified = ( authorization , secret , key , cb ? , returnCallback ? ) => { if ( ! authorization || ! secret || ! key ) { console . error ( 'authorization or app secret or app key missing' ) ; return false ; } const auth = authorization . replace ( 'Bearer ' , '' ) . split ( '.' ) ; const authObject = { header : atob ( auth [ 0 ] ) , payload : atob ( auth [ 1 ] ) , signature : auth [ 2 ] } ; const headerPayload = [ auth [ 0 ] , auth [ 1 ] ] . join ( '.' ) ; const signedBuffer = crypto . createHmac ( 'sha256' , secret ) . update ( headerPayload ) . digest ( ) ; const isVerified = authObject . signature === base64UrlEncode ( signedBuffer ) ; if ( ! isVerified ) { console . error ( 'Token is invalid' ) ; return false ; } const payload = JSON . parse ( authObject . payload ) ; const time = new Date ( ) . getTime ( ) / 1000 ; const isExpired = payload . exp <= time ; const isValidAfter = payload . nbf <= time ; const iss = new URL ( payload . iss ) . hostname ; const dest = new URL ( payload . dest ) . hostname ; if ( isExpired ) { console . error ( 'Token is expired' ) ; return false ; } if ( ! isValidAfter ) { console . error ( 'Token is not yet valid' ) ; return false ; } if ( iss != dest ) { console . error ( `Token issuer ${ iss } does not match the destination ${ dest }` ) ; return false ; } if ( payload . aud != key ) { console . error ( 'Token does not match the Shopify API Key' ) ; return false ; } if ( cb && ! returnCallback ) { cb ( authObject , payload ) ; } return ! returnCallback ? true : cb ( authObject , payload ) ; } ; export default isVerified ;