import { Inject , Injectable , Logger } from '@nestjs/common' ; import * as jwt from 'jsonwebtoken' ; import { JwtModuleOptions , JwtSecretRequestType , JwtSignOptions , JwtVerifyOptions } from './interfaces/jwt-module-options.interface' ; import { JWT_MODULE_OPTIONS } from './jwt.constants' ; @ Injectable ( ) export class JwtService { private readonly logger = new Logger ( 'JwtService' ) ; constructor ( @ Inject ( JWT_MODULE_OPTIONS ) private readonly options ) { } sign ( payload , options ? ) { const signOptions = this . mergeJwtOptions ( { ... options } , 'signOptions' ) as jwt . SignOptions ; const secret = this . getSecretKey ( payload , options , 'privateKey' , JwtSecretRequestType . SIGN ) ; return jwt . sign ( payload , secret , signOptions ) ; } signAsync ( payload , options ? ) { const signOptions = this . mergeJwtOptions ( { ... options } , 'signOptions' ) as jwt . SignOptions ; const secret = this . getSecretKey ( payload , options , 'privateKey' , JwtSecretRequestType . SIGN ) ; return new Promise ( ( resolve , reject ) => jwt . sign ( payload , secret , signOptions , ( err , encoded ) => err ? reject ( err ) : resolve ( encoded ) ) ) ; } verify < T extends object = any > ( token , options ? ) { const verifyOptions = this . mergeJwtOptions ( { ... options } , 'verifyOptions' ) ; const secret = this . getSecretKey ( token , options , 'publicKey' , JwtSecretRequestType . VERIFY ) ; return jwt . verify ( token , secret , verifyOptions ) as T ; } verifyAsync < T extends object = any > ( token , options ? ) { const verifyOptions = this . mergeJwtOptions ( { ... options } , 'verifyOptions' ) ; const secret = this . getSecretKey ( token , options , 'publicKey' , JwtSecretRequestType . VERIFY ) ; return new Promise ( ( resolve , reject ) => jwt . verify ( token , secret , verifyOptions , ( err , decoded ) => err ? reject ( err ) : resolve ( decoded as T ) ) ) as Promise < T > ; } decode ( token , options ? ) { return jwt . decode ( token , options ) ; } private mergeJwtOptions ( options , key ) { delete options . secret ; if ( key === 'signOptions' ) { delete ( options as JwtSignOptions ) . privateKey ; } else { delete ( options as JwtVerifyOptions ) . publicKey ; } return options ? { ... ( this . options [ key ] || { } ) , ... options } : this . options [ key ] ; } private getSecretKey ( token , options , key , secretRequestType ) { let secret = this . options . secretOrKeyProvider ? this . options . secretOrKeyProvider ( secretRequestType , token , options ) : options ?. secret || this . options . secret || ( key === 'privateKey' ? ( options as JwtSignOptions ) ?. privateKey || this . options . privateKey : ( options as JwtVerifyOptions ) ?. publicKey || this . options . publicKey ) || this . options [ key ] ; if ( this . options . secretOrPrivateKey ) { this . logger . warn ( `"secretOrPrivateKey" has been deprecated, please use the new explicit "secret" or use "secretOrKeyProvider" or "privateKey"/"publicKey" exclusively.` ) ; secret = this . options . secretOrPrivateKey ; } return secret ; } }