@@ -34,6 +34,12 @@ import type { ParamsIncomingMessage } from './ParamsIncomingMessage';
3434import { type CustomRoute , type ReceiverRoutes , buildReceiverRoutes } from './custom-routes' ;
3535import { verifyRedirectOpts } from './verify-redirect-opts' ;
3636
37+ export interface HTTPReceiverInvalidRequestSignatureHandlerArgs {
38+ rawBody : string ;
39+ signature : string | undefined ;
40+ ts : number | undefined ;
41+ }
42+
3743// Option keys for tls.createServer() and tls.createSecureContext(), exclusive of those for http.createServer()
3844const httpsOptionKeys = [
3945 'ALPNProtocols' ,
@@ -81,6 +87,7 @@ export interface HTTPReceiverOptions {
8187 logLevel ?: LogLevel ;
8288 processBeforeResponse ?: boolean ;
8389 signatureVerification ?: boolean ;
90+ invalidRequestSignatureHandler ?: ( args : HTTPReceiverInvalidRequestSignatureHandlerArgs ) => void ;
8491 clientId ?: string ;
8592 clientSecret ?: string ;
8693 stateSecret ?: InstallProviderOptions [ 'stateSecret' ] ; // required when using default stateStore
@@ -137,6 +144,8 @@ export default class HTTPReceiver implements Receiver {
137144
138145 private signatureVerification : boolean ;
139146
147+ private invalidRequestSignatureHandler : ( args : HTTPReceiverInvalidRequestSignatureHandlerArgs ) => void ;
148+
140149 private app ?: App ;
141150
142151 public requestListener : RequestListener ;
@@ -178,6 +187,7 @@ export default class HTTPReceiver implements Receiver {
178187 logLevel = LogLevel . INFO ,
179188 processBeforeResponse = false ,
180189 signatureVerification = true ,
190+ invalidRequestSignatureHandler,
181191 clientId = undefined ,
182192 clientSecret = undefined ,
183193 stateSecret = undefined ,
@@ -195,6 +205,8 @@ export default class HTTPReceiver implements Receiver {
195205 this . signingSecret = signingSecret ;
196206 this . processBeforeResponse = processBeforeResponse ;
197207 this . signatureVerification = signatureVerification ;
208+ this . invalidRequestSignatureHandler =
209+ invalidRequestSignatureHandler ?? this . defaultInvalidRequestSignatureHandler . bind ( this ) ;
198210 this . logger =
199211 logger ??
200212 ( ( ) => {
@@ -448,6 +460,13 @@ export default class HTTPReceiver implements Receiver {
448460 const e = err as Error ;
449461 if ( this . signatureVerification ) {
450462 this . logger . warn ( `Failed to parse and verify the request data: ${ e . message } ` ) ;
463+ const requestWithRawBody = req as IncomingMessage & { rawBody ?: string } ;
464+ const rawBody = typeof requestWithRawBody . rawBody === 'string' ? requestWithRawBody . rawBody : '' ;
465+ this . invalidRequestSignatureHandler ( {
466+ rawBody,
467+ signature : req . headers [ 'x-slack-signature' ] as string | undefined ,
468+ ts : req . headers [ 'x-slack-request-timestamp' ] ? Number ( req . headers [ 'x-slack-request-timestamp' ] ) : undefined ,
469+ } ) ;
451470 } else {
452471 this . logger . warn ( `Failed to parse the request body: ${ e . message } ` ) ;
453472 }
@@ -565,4 +584,8 @@ export default class HTTPReceiver implements Receiver {
565584 installer . handleCallback ( req , res , installCallbackOptions ) . catch ( errorHandler ) ;
566585 }
567586 }
587+
588+ private defaultInvalidRequestSignatureHandler ( _args : HTTPReceiverInvalidRequestSignatureHandlerArgs ) : void {
589+ // noop - signature verification failure is already logged and a 401 is returned
590+ }
568591}
0 commit comments