
























@@ -304,7 +304,7 @@ describe("monitorMSTeamsProvider lifecycle", () => {
304304).rejects.toThrow(/EADDRINUSE/);
305305});
306306307-it("runs JWT validation before JSON body parsing", async () => {
307+it("parses bounded JSON after the Bearer gate and binds serviceUrl during JWT validation", async () => {
308308const abort = new AbortController();
309309const task = monitorMSTeamsProvider({
310310cfg: createConfig(0),
@@ -322,23 +322,41 @@ describe("monitorMSTeamsProvider lifecycle", () => {
322322if (!app) {
323323throw new Error("expected Express app to be created");
324324}
325+// This test intentionally locks auth middleware ordering: the cheap Bearer
326+// gate must run before bounded JSON parsing, and JWT validation must run
327+// after parsing so it can bind the token to Activity.serviceUrl.
325328expect(app.use).toHaveBeenCalledTimes(4);
326329327330const jsonMiddleware = vi.mocked((await import("express")).json).mock.results[0]?.value;
328331if (typeof jsonMiddleware !== "function") {
329332throw new Error("expected Express JSON middleware");
330333}
331-expect(readMockCallArg(app.use, 1, 0)).not.toBe(jsonMiddleware);
332-expect(readMockCallArg(app.use, 2, 0)).toBe(jsonMiddleware);
334+expect(readMockCallArg(app.use, 1, 0)).toBe(jsonMiddleware);
333335334-const jwtMiddleware = readMockCallArg(app.use, 1, 0) as (
336+const authGate = readMockCallArg(app.use, 0, 0) as (
337+req: Request,
338+res: Response,
339+next: (err?: unknown) => void,
340+) => void;
341+const authNext = vi.fn();
342+const unauthorizedResponse = {
343+status: vi.fn().mockReturnThis(),
344+json: vi.fn(),
345+} as unknown as Response;
346+authGate({ headers: {} } as Request, unauthorizedResponse, authNext);
347+expect(authNext).not.toHaveBeenCalled();
348+349+const jwtMiddleware = readMockCallArg(app.use, 3, 0) as (
335350req: Request,
336351res: Response,
337352next: (err?: unknown) => void,
338353) => void;
339354const next = vi.fn();
340355jwtMiddleware(
341-{ headers: { authorization: "Bearer token" } } as Request,
356+{
357+headers: { authorization: "Bearer token" },
358+body: { serviceUrl: "https://smba.trafficmanager.net/amer/" },
359+} as Request,
342360{
343361status: vi.fn().mockReturnThis(),
344362json: vi.fn(),
@@ -347,10 +365,34 @@ describe("monitorMSTeamsProvider lifecycle", () => {
347365);
348366349367await vi.waitFor(() => {
350-expect(jwtValidate).toHaveBeenCalledWith("Bearer token");
368+expect(jwtValidate).toHaveBeenCalledWith(
369+"Bearer token",
370+"https://smba.trafficmanager.net/amer/",
371+);
351372expect(next).toHaveBeenCalledTimes(1);
352373});
353374375+jwtValidate.mockReset().mockResolvedValueOnce(false);
376+const missingServiceUrlNext = vi.fn();
377+const missingServiceUrlResponse = {
378+status: vi.fn().mockReturnThis(),
379+json: vi.fn(),
380+} as unknown as Response;
381+jwtMiddleware(
382+{
383+headers: { authorization: "Bearer token-no-service-url" },
384+body: { type: "message" },
385+} as Request,
386+missingServiceUrlResponse,
387+missingServiceUrlNext,
388+);
389+390+await vi.waitFor(() => {
391+expect(jwtValidate).toHaveBeenCalledWith("Bearer token-no-service-url", undefined);
392+expect(missingServiceUrlResponse.status).toHaveBeenCalledWith(401);
393+expect(missingServiceUrlNext).not.toHaveBeenCalled();
394+});
395+354396abort.abort();
355397await task;
356398});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。