@@ -19,23 +19,41 @@ import { getOAuthToken, refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/
1919
2020const logger = createLogger ( 'WebhookProvider:Webflow' )
2121
22- function validateWebflowSignature ( secret : string , signature : string , rawBody : string ) : boolean {
23- const computed = hmacSha256Hex ( rawBody , secret )
22+ function validateWebflowSignature (
23+ secret : string ,
24+ signature : string ,
25+ timestamp : string ,
26+ rawBody : string
27+ ) : boolean {
28+ const computed = hmacSha256Hex ( `${ timestamp } :${ rawBody } ` , secret )
2429 return safeCompare ( computed , signature )
2530}
2631
32+ const FIVE_MINUTES_MS = 5 * 60 * 1000
33+
2734export const webflowHandler : WebhookProviderHandler = {
2835 verifyAuth ( { request, rawBody, requestId, providerConfig } : AuthContext ) {
2936 const secret = providerConfig . webhookSecret as string | undefined
3037 if ( ! secret ) return null
3138
39+ const timestamp = request . headers . get ( 'x-webflow-timestamp' )
40+ if ( ! timestamp ) {
41+ logger . warn ( `[${ requestId } ] Webflow webhook missing X-Webflow-Timestamp header` )
42+ return new NextResponse ( 'Unauthorized - Missing Webflow timestamp' , { status : 401 } )
43+ }
44+
3245 const signature = request . headers . get ( 'x-webflow-signature' )
3346 if ( ! signature ) {
3447 logger . warn ( `[${ requestId } ] Webflow webhook missing X-Webflow-Signature header` )
3548 return new NextResponse ( 'Unauthorized - Missing Webflow signature' , { status : 401 } )
3649 }
3750
38- if ( ! validateWebflowSignature ( secret , signature , rawBody ) ) {
51+ if ( Math . abs ( Date . now ( ) - Number ( timestamp ) ) > FIVE_MINUTES_MS ) {
52+ logger . warn ( `[${ requestId } ] Webflow webhook timestamp too old, possible replay attack` )
53+ return new NextResponse ( 'Unauthorized - Webflow timestamp expired' , { status : 401 } )
54+ }
55+
56+ if ( ! validateWebflowSignature ( secret , signature , timestamp , rawBody ) ) {
3957 logger . warn ( `[${ requestId } ] Webflow signature verification failed` )
4058 return new NextResponse ( 'Unauthorized - Invalid Webflow signature' , { status : 401 } )
4159 }
@@ -162,7 +180,7 @@ export const webflowHandler: WebhookProviderHandler = {
162180 return {
163181 providerConfigUpdates : {
164182 externalId : responseBody . id || responseBody . _id ,
165- ...( responseBody . secretToken ? { webhookSecret : responseBody . secretToken } : { } ) ,
183+ ...( responseBody . secretKey ? { webhookSecret : responseBody . secretKey } : { } ) ,
166184 } ,
167185 }
168186 } catch ( error : unknown ) {
0 commit comments