Microsoft Teams accepts the new Power Automate webhook URL format

This commit is contained in:
Jarek Krochmalski committed 2026-09-06 17:03:48 +05:30
1 parent 369a9b17cf
commit e35b825e38
3 files changed
+86 -7

No files matched your search

+4 -6
View File
@@ -1,14 +1,12 @@
/** Microsoft Power Automate Workflows (e.g. Microsoft Teams). workflows://. */
import { parseWorkflowsUrl, buildWorkflowsHttpUrl } from '$lib/utils/notification-parsers';
import { resolveWorkflowsHttpUrl } from '$lib/utils/notification-parsers';
import { notificationFetch, drainResponse, type NotificationPayload, type NotificationResult } from './shared';
export async function sendWorkflows(appriseUrl: string, payload: NotificationPayload): Promise<NotificationResult> {
const parsed = parseWorkflowsUrl(appriseUrl);
if (!parsed) {
return { success: false, error: 'Invalid Workflows URL format. Expected: workflows://hostname/workflow/signature' };
const url = resolveWorkflowsHttpUrl(appriseUrl);
if (!url) {
return { success: false, error: 'Invalid Workflows URL format. Expected the full https:// webhook URL with the scheme changed to workflows://, or workflows://hostname/workflow/signature' };
}
const url = buildWorkflowsHttpUrl(parsed.hostname, parsed.workflow, parsed.signature);
const titleWithEnv = payload.environmentName ? `${payload.title} [${payload.environmentName}]` : payload.title;
try {
+37
View File
@@ -97,3 +97,40 @@ export function parseWorkflowsUrl(appriseUrl: string): { hostname: string; workf
export function buildWorkflowsHttpUrl(hostname: string, workflow: string, signature: string): string {
return `https://${hostname}/powerautomate/automations/direct/workflows/${workflow}/triggers/manual/paths/invoke?api-version=1&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=${signature}`;
}
/**
* Resolve a `workflows://` channel URL to the HTTPS endpoint to POST to.
*
* Two input shapes are accepted:
* 1. A COMPLETE webhook URL with the schema swapped to `workflows://` - i.e. it
* already carries the full `/.../triggers/manual/paths/invoke?...&sig=...` path
* and query. Microsoft has changed this path over time (legacy logic.azure.com,
* then `/powerautomate/automations/direct/`, then a `/cu/<n>/` segment on
* *.powerplatform.com - #1512). We must NOT rebuild it from parts, or new
* segments and query params (api-version, cu/<n>) get dropped -> 401. So when the
* input already has the invoke path + a sig, pass the path and query through
* verbatim, only swapping the scheme to https.
* 2. The SHORT legacy form `workflows://host/<workflow>/<signature>` (what the UI
* hint documents). No invoke path, so reconstruct the endpoint as before.
*
* Returns the https URL, or null when the input is neither shape.
*/
export function resolveWorkflowsHttpUrl(appriseUrl: string): string | null {
const schemeMatch = appriseUrl.match(/^workflows?:\/\/(.*)$/is);
if (!schemeMatch) return null;
const rest = schemeMatch[1];
// Shape 1: a full webhook URL - it carries the invoke path. Pass it through
// verbatim (only when it also has a sig=, else it's an unsigned/invalid webhook)
// so any host/path/query shape Microsoft uses survives. An invoke path present but
// no sig is invalid - do NOT fall through to short-form parsing, which would shred
// the path into a bogus workflow/signature.
if (/\/triggers\/manual\/paths\/invoke/i.test(rest)) {
return /[?&]sig=[^&]/i.test(rest) ? `https://${rest}` : null;
}
// Shape 2: the short legacy form host/<workflow>/<signature>.
const parsed = parseWorkflowsUrl(appriseUrl);
if (!parsed) return null;
return buildWorkflowsHttpUrl(parsed.hostname, parsed.workflow, parsed.signature);
}