({ webhook, request, rawBody, requestId, providerConfig }: AuthContext)
| 478 | }, |
| 479 | |
| 480 | verifyAuth({ webhook, request, rawBody, requestId, providerConfig }: AuthContext) { |
| 481 | if (providerConfig.hmacSecret) { |
| 482 | const authHeader = request.headers.get('authorization') |
| 483 | |
| 484 | if (!authHeader || !authHeader.startsWith('HMAC ')) { |
| 485 | logger.warn( |
| 486 | `[${requestId}] Microsoft Teams outgoing webhook missing HMAC authorization header` |
| 487 | ) |
| 488 | return new NextResponse('Unauthorized - Missing HMAC signature', { status: 401 }) |
| 489 | } |
| 490 | |
| 491 | if ( |
| 492 | !validateMicrosoftTeamsSignature(providerConfig.hmacSecret as string, authHeader, rawBody) |
| 493 | ) { |
| 494 | logger.warn(`[${requestId}] Microsoft Teams HMAC signature verification failed`) |
| 495 | return new NextResponse('Unauthorized - Invalid HMAC signature', { status: 401 }) |
| 496 | } |
| 497 | } |
| 498 | |
| 499 | if (providerConfig.triggerId === 'microsoftteams_chat_subscription') { |
| 500 | const expectedClientState = String(webhook.id ?? '') |
| 501 | if (!expectedClientState) { |
| 502 | logger.warn( |
| 503 | `[${requestId}] Microsoft Teams chat subscription webhook missing id for clientState verification` |
| 504 | ) |
| 505 | return new NextResponse('Unauthorized - Invalid clientState', { status: 401 }) |
| 506 | } |
| 507 | |
| 508 | let notifications: unknown[] = [] |
| 509 | try { |
| 510 | const parsed = JSON.parse(rawBody) as Record<string, unknown> |
| 511 | if (Array.isArray(parsed?.value)) { |
| 512 | notifications = parsed.value |
| 513 | } |
| 514 | } catch { |
| 515 | notifications = [] |
| 516 | } |
| 517 | |
| 518 | if (notifications.length === 0) { |
| 519 | logger.warn( |
| 520 | `[${requestId}] Microsoft Teams chat subscription notification missing value array` |
| 521 | ) |
| 522 | return new NextResponse('Unauthorized - Invalid notification payload', { status: 401 }) |
| 523 | } |
| 524 | |
| 525 | for (const notification of notifications) { |
| 526 | const clientState = (notification as Record<string, unknown>)?.clientState |
| 527 | if (typeof clientState !== 'string' || !safeCompare(clientState, expectedClientState)) { |
| 528 | logger.warn( |
| 529 | `[${requestId}] Microsoft Teams chat subscription clientState verification failed` |
| 530 | ) |
| 531 | return new NextResponse('Unauthorized - Invalid clientState', { status: 401 }) |
| 532 | } |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | return null |
| 537 | }, |
nothing calls this directly
no test coverage detected