From 4b219d12e4e0c4d5442cb09e45338bb033995d2a Mon Sep 17 00:00:00 2001 From: Tyagiquamar Date: Sun, 13 Sep 2026 20:26:14 +0530 Subject: [PATCH 1/4] fix(toolkit): disallow none combined with other prompts in oidcPromptsGuard (#9565) --- .../connector-kit/src/types/social.test.ts | 21 +++++++++++++++++++ .../toolkit/connector-kit/src/types/social.ts | 3 +++ 2 files changed, 24 insertions(+) create mode 100644 packages/toolkit/connector-kit/src/types/social.test.ts diff --git a/packages/toolkit/connector-kit/src/types/social.test.ts b/packages/toolkit/connector-kit/src/types/social.test.ts new file mode 100644 index 000000000000..c936211eb1e4 --- /dev/null +++ b/packages/toolkit/connector-kit/src/types/social.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest'; + +import { oidcPromptsGuard, OidcPrompt } from './social.js'; + +describe('oidcPromptsGuard', () => { + it('allows single prompt values including none', () => { + expect(oidcPromptsGuard.safeParse([OidcPrompt.None]).success).toBe(true); + expect(oidcPromptsGuard.safeParse([OidcPrompt.Consent]).success).toBe(true); + expect(oidcPromptsGuard.safeParse([OidcPrompt.SelectAccount, OidcPrompt.Consent]).success).toBe(true); + expect(oidcPromptsGuard.safeParse(undefined).success).toBe(true); + }); + + it('rejects none when combined with other prompts', () => { + const result = oidcPromptsGuard.safeParse([ + OidcPrompt.SelectAccount, + OidcPrompt.Consent, + OidcPrompt.None, + ]); + expect(result.success).toBe(false); + }); +}); diff --git a/packages/toolkit/connector-kit/src/types/social.ts b/packages/toolkit/connector-kit/src/types/social.ts index 9190d739279f..d5a6617e38e1 100644 --- a/packages/toolkit/connector-kit/src/types/social.ts +++ b/packages/toolkit/connector-kit/src/types/social.ts @@ -18,6 +18,9 @@ export type OidcPrompts = OidcPrompt[]; export const oidcPromptsGuard: z.ZodType> = z .nativeEnum(OidcPrompt) .array() + .refine((prompts) => !prompts.includes(OidcPrompt.None) || prompts.length === 1, { + message: 'The `none` prompt cannot be combined with other prompts.', + }) .optional(); // This type definition is for SAML connector From 2aee1a49061de7f53e43627a37224a309438fba5 Mon Sep 17 00:00:00 2001 From: Tyagiquamar Date: Mon, 14 Sep 2026 12:26:10 +0530 Subject: [PATCH 2/4] test(toolkit): add changeset and accurately describe valid prompt configurations Signed-off-by: Tyagiquamar --- .changeset/oidc-prompt-none-validation.md | 5 +++++ packages/toolkit/connector-kit/src/types/social.test.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/oidc-prompt-none-validation.md diff --git a/.changeset/oidc-prompt-none-validation.md b/.changeset/oidc-prompt-none-validation.md new file mode 100644 index 000000000000..94123d6b8609 --- /dev/null +++ b/.changeset/oidc-prompt-none-validation.md @@ -0,0 +1,5 @@ +--- +"@logto/connector-kit": patch +--- + +disallow `none` combined with other prompts in `oidcPromptsGuard` diff --git a/packages/toolkit/connector-kit/src/types/social.test.ts b/packages/toolkit/connector-kit/src/types/social.test.ts index c936211eb1e4..ee2369294e64 100644 --- a/packages/toolkit/connector-kit/src/types/social.test.ts +++ b/packages/toolkit/connector-kit/src/types/social.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it } from 'vitest'; import { oidcPromptsGuard, OidcPrompt } from './social.js'; describe('oidcPromptsGuard', () => { - it('allows single prompt values including none', () => { + it('allows valid prompt configurations, including undefined, single prompts, and combinations without none', () => { expect(oidcPromptsGuard.safeParse([OidcPrompt.None]).success).toBe(true); expect(oidcPromptsGuard.safeParse([OidcPrompt.Consent]).success).toBe(true); expect(oidcPromptsGuard.safeParse([OidcPrompt.SelectAccount, OidcPrompt.Consent]).success).toBe(true); From cd0fb71c34b262682bf54899265d87347e195e48 Mon Sep 17 00:00:00 2001 From: Tyagiquamar Date: Mon, 14 Sep 2026 12:33:55 +0530 Subject: [PATCH 3/4] docs(toolkit): rephrase changeset description for user-facing behavior Signed-off-by: Tyagiquamar --- .changeset/oidc-prompt-none-validation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/oidc-prompt-none-validation.md b/.changeset/oidc-prompt-none-validation.md index 94123d6b8609..4deb28ec2c5b 100644 --- a/.changeset/oidc-prompt-none-validation.md +++ b/.changeset/oidc-prompt-none-validation.md @@ -2,4 +2,4 @@ "@logto/connector-kit": patch --- -disallow `none` combined with other prompts in `oidcPromptsGuard` +disallow combining the `none` prompt with other prompt values in OIDC configuration From 3d5655b8ff349ecfe819e06353ec4a8940993ca2 Mon Sep 17 00:00:00 2001 From: logto-maintainer Date: Tue, 15 Sep 2026 06:12:52 +0000 Subject: [PATCH 4/4] fix(toolkit): resolve lint errors in oidcPromptsGuard tests --- packages/toolkit/connector-kit/src/types/social.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/toolkit/connector-kit/src/types/social.test.ts b/packages/toolkit/connector-kit/src/types/social.test.ts index ee2369294e64..1b8e28c13df6 100644 --- a/packages/toolkit/connector-kit/src/types/social.test.ts +++ b/packages/toolkit/connector-kit/src/types/social.test.ts @@ -6,7 +6,10 @@ describe('oidcPromptsGuard', () => { it('allows valid prompt configurations, including undefined, single prompts, and combinations without none', () => { expect(oidcPromptsGuard.safeParse([OidcPrompt.None]).success).toBe(true); expect(oidcPromptsGuard.safeParse([OidcPrompt.Consent]).success).toBe(true); - expect(oidcPromptsGuard.safeParse([OidcPrompt.SelectAccount, OidcPrompt.Consent]).success).toBe(true); + expect(oidcPromptsGuard.safeParse([OidcPrompt.SelectAccount, OidcPrompt.Consent]).success).toBe( + true + ); + // eslint-disable-next-line unicorn/no-useless-undefined -- undefined is a valid optional value under test expect(oidcPromptsGuard.safeParse(undefined).success).toBe(true); });