mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-01 08:00:22 +00:00
fix: preserve Teams Entra JWT fallback on legacy validator errors
This commit is contained in:
@@ -173,6 +173,38 @@ describe("createBotFrameworkJwtValidator", () => {
|
||||
expect(entraConfig?.validateIssuer).toEqual({ allowedTenantIds: ["tenant-id"] });
|
||||
});
|
||||
|
||||
it("falls back to Entra JWKS when Bot Framework validation throws", async () => {
|
||||
jwtValidatorState.behaviorByJwks.set(
|
||||
"https://login.botframework.com/v1/.well-known/keys",
|
||||
"throw",
|
||||
);
|
||||
jwtValidatorState.behaviorByJwks.set(
|
||||
"https://login.microsoftonline.com/common/discovery/v2.0/keys",
|
||||
"success",
|
||||
);
|
||||
|
||||
const validator = await createBotFrameworkJwtValidator(creds);
|
||||
await expect(
|
||||
validator.validate("Bearer token-throw", "https://service.example.com"),
|
||||
).resolves.toBe(true);
|
||||
|
||||
expect(jwtValidatorState.calls).toHaveLength(2);
|
||||
expect(jwtValidatorState.calls[0]).toMatchObject({
|
||||
jwksUri: "https://login.botframework.com/v1/.well-known/keys",
|
||||
token: "token-throw",
|
||||
overrideOptions: {
|
||||
validateServiceUrl: { expectedServiceUrl: "https://service.example.com" },
|
||||
},
|
||||
});
|
||||
expect(jwtValidatorState.calls[1]).toMatchObject({
|
||||
jwksUri: "https://login.microsoftonline.com/common/discovery/v2.0/keys",
|
||||
token: "token-throw",
|
||||
overrideOptions: {
|
||||
validateServiceUrl: { expectedServiceUrl: "https://service.example.com" },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("returns false when all validator paths fail", async () => {
|
||||
jwtValidatorState.behaviorByJwks.set(
|
||||
"https://login.botframework.com/v1/.well-known/keys",
|
||||
@@ -181,6 +213,7 @@ describe("createBotFrameworkJwtValidator", () => {
|
||||
|
||||
const validator = await createBotFrameworkJwtValidator(creds);
|
||||
await expect(validator.validate("Bearer token-3")).resolves.toBe(false);
|
||||
expect(jwtValidatorState.calls).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("returns false for empty bearer token", async () => {
|
||||
|
||||
@@ -439,6 +439,23 @@ export async function createBotFrameworkJwtValidator(creds: MSTeamsCredentials):
|
||||
},
|
||||
});
|
||||
|
||||
async function validateWithFallback(
|
||||
token: string,
|
||||
overrides: { validateServiceUrl: { expectedServiceUrl: string } } | undefined,
|
||||
): Promise<boolean> {
|
||||
for (const validator of [botFrameworkValidator, entraValidator]) {
|
||||
try {
|
||||
const result = await validator.validateAccessToken(token, overrides);
|
||||
if (result != null) {
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
async validate(authHeader: string, serviceUrl?: string): Promise<boolean> {
|
||||
const token = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : authHeader;
|
||||
@@ -449,18 +466,7 @@ export async function createBotFrameworkJwtValidator(creds: MSTeamsCredentials):
|
||||
const overrides = serviceUrl
|
||||
? ({ validateServiceUrl: { expectedServiceUrl: serviceUrl } } as const)
|
||||
: undefined;
|
||||
|
||||
try {
|
||||
const legacyResult = await botFrameworkValidator.validateAccessToken(token, overrides);
|
||||
if (legacyResult != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const entraResult = await entraValidator.validateAccessToken(token, overrides);
|
||||
return entraResult != null;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
return await validateWithFallback(token, overrides);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user