@zitadel/config 1.0.0-alpha.24 → 1.0.0-alpha.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/defaults/branding/centered/login.liquid +31 -11
  2. package/defaults/branding/minimal/login.liquid +30 -10
  3. package/dist/branding-contrast.d.mts +28 -21
  4. package/dist/branding-contrast.d.mts.map +1 -1
  5. package/dist/branding-contrast.mjs +1 -1
  6. package/dist/branding-contrast.mjs.map +1 -1
  7. package/dist/branding-url.d.mts +1 -2
  8. package/dist/branding-url.d.mts.map +1 -1
  9. package/dist/branding-url.mjs.map +1 -1
  10. package/dist/css-color.d.mts +5 -10
  11. package/dist/css-color.d.mts.map +1 -1
  12. package/dist/css-color.mjs +1 -1
  13. package/dist/css-color.mjs.map +1 -1
  14. package/dist/{defaults-BnWXllBk.d.mts → defaults-BtKIcWxW.d.mts} +11 -7
  15. package/dist/defaults-BtKIcWxW.d.mts.map +1 -0
  16. package/dist/{defaults-BnRHT7RQ.mjs → defaults-COLBFU3S.mjs} +1 -1
  17. package/dist/defaults-COLBFU3S.mjs.map +1 -0
  18. package/dist/defaults.d.mts +1 -1
  19. package/dist/defaults.mjs +1 -1
  20. package/dist/idp/index.d.mts +2 -0
  21. package/dist/idp/index.mjs +2 -0
  22. package/dist/idp-ByzXQN85.mjs +207 -0
  23. package/dist/idp-ByzXQN85.mjs.map +1 -0
  24. package/dist/idp-connection-CHxGm1Wr.mjs +324 -0
  25. package/dist/idp-connection-CHxGm1Wr.mjs.map +1 -0
  26. package/dist/index-Cuxu-zQD.d.mts +210 -0
  27. package/dist/index-Cuxu-zQD.d.mts.map +1 -0
  28. package/dist/index.d.mts +4 -3
  29. package/dist/index.mjs +5 -4
  30. package/dist/{meta-schemas-K8f7YZYz.mjs → meta-schemas-C03zgFux.mjs} +31 -328
  31. package/dist/meta-schemas-C03zgFux.mjs.map +1 -0
  32. package/dist/meta-schemas.d.mts +5 -6
  33. package/dist/meta-schemas.d.mts.map +1 -1
  34. package/dist/meta-schemas.mjs +1 -1
  35. package/dist/normalize.d.mts +3 -4
  36. package/dist/normalize.d.mts.map +1 -1
  37. package/dist/normalize.mjs.map +1 -1
  38. package/dist/{schemas-7oNU25Qz.mjs → schemas-CUU4Rf8J.mjs} +11 -4
  39. package/dist/schemas-CUU4Rf8J.mjs.map +1 -0
  40. package/dist/schemas.d.mts +361 -9
  41. package/dist/schemas.d.mts.map +1 -1
  42. package/dist/schemas.mjs +2 -2
  43. package/dist/template.d.mts +9 -10
  44. package/dist/template.d.mts.map +1 -1
  45. package/dist/template.mjs.map +1 -1
  46. package/dist/validate.d.mts +15 -13
  47. package/dist/validate.d.mts.map +1 -1
  48. package/dist/validate.mjs +28 -18
  49. package/dist/validate.mjs.map +1 -1
  50. package/meta-schemas/flow-definition.json +81 -6
  51. package/package.json +12 -6
  52. package/dist/defaults-BnRHT7RQ.mjs.map +0 -1
  53. package/dist/defaults-BnWXllBk.d.mts.map +0 -1
  54. package/dist/meta-schemas-K8f7YZYz.mjs.map +0 -1
  55. package/dist/schemas-7oNU25Qz.mjs.map +0 -1
package/dist/defaults.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as brandingReadmeContent, a as DEFAULT_BUILTIN_SCHEMA_BASE, c as DEFAULT_SCHEMA_CONFIG_PATH, d as SETUP_PRESETS, f as SETUP_USE_CASES, g as getDefaultLoginFlow, h as getDefaultHumanUserSchema, i as DEFAULT_BRANDING_TEMPLATE_PATH, l as DEFAULT_SETUP_PRESET, m as getDefaultBrandingConfig, n as DEFAULT_BRANDING_CONFIG_PATH, o as DEFAULT_FLOW_CONFIG_PATH, p as defaultHumanUserSchemaUrl, r as DEFAULT_BRANDING_DESIGN, s as DEFAULT_FLOW_SCHEMA_URI, t as BRANDING_DESIGNS, u as DEFAULT_SETUP_USE_CASE, v as flowsReadmeContent, y as schemasReadmeContent } from "./defaults-BnRHT7RQ.mjs";
1
+ import { _ as brandingReadmeContent, a as DEFAULT_BUILTIN_SCHEMA_BASE, c as DEFAULT_SCHEMA_CONFIG_PATH, d as SETUP_PRESETS, f as SETUP_USE_CASES, g as getDefaultLoginFlow, h as getDefaultHumanUserSchema, i as DEFAULT_BRANDING_TEMPLATE_PATH, l as DEFAULT_SETUP_PRESET, m as getDefaultBrandingConfig, n as DEFAULT_BRANDING_CONFIG_PATH, o as DEFAULT_FLOW_CONFIG_PATH, p as defaultHumanUserSchemaUrl, r as DEFAULT_BRANDING_DESIGN, s as DEFAULT_FLOW_SCHEMA_URI, t as BRANDING_DESIGNS, u as DEFAULT_SETUP_USE_CASE, v as flowsReadmeContent, y as schemasReadmeContent } from "./defaults-COLBFU3S.mjs";
2
2
  export { BRANDING_DESIGNS, DEFAULT_BRANDING_CONFIG_PATH, DEFAULT_BRANDING_DESIGN, DEFAULT_BRANDING_TEMPLATE_PATH, DEFAULT_BUILTIN_SCHEMA_BASE, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, DEFAULT_SETUP_PRESET, DEFAULT_SETUP_USE_CASE, SETUP_PRESETS, SETUP_USE_CASES, brandingReadmeContent, defaultHumanUserSchemaUrl, flowsReadmeContent, getDefaultBrandingConfig, getDefaultHumanUserSchema, getDefaultLoginFlow, schemasReadmeContent };
@@ -0,0 +1,2 @@
1
+ import { a as ISSUER_REQUIREMENT, c as ConnectionEndpoints, d as ScaffoldOptions, f as credentialVariable, g as variableReference, h as referencedVariable, i as OidcProvider, l as CredentialVariables, m as isVariableReference, n as idpProvider, o as isSupportedIssuer, p as credentialVariables, r as GoogleProvider, s as CallbackGuidance, t as IDP_PROVIDERS, u as IdpProvider } from "../index-Cuxu-zQD.mjs";
2
+ export { type CallbackGuidance, type ConnectionEndpoints, type CredentialVariables, GoogleProvider, IDP_PROVIDERS, ISSUER_REQUIREMENT, type IdpProvider, OidcProvider, type ScaffoldOptions, credentialVariable, credentialVariables, idpProvider, isSupportedIssuer, isVariableReference, referencedVariable, variableReference };
@@ -0,0 +1,2 @@
1
+ import { a as GoogleProvider, c as credentialVariables, d as variableReference, i as isSupportedIssuer, l as isVariableReference, n as idpProvider, o as OidcProvider, r as ISSUER_REQUIREMENT, s as credentialVariable, t as IDP_PROVIDERS, u as referencedVariable } from "../idp-ByzXQN85.mjs";
2
+ export { GoogleProvider, IDP_PROVIDERS, ISSUER_REQUIREMENT, OidcProvider, credentialVariable, credentialVariables, idpProvider, isSupportedIssuer, isVariableReference, referencedVariable, variableReference };
@@ -0,0 +1,207 @@
1
+ import { t as idp_connection_default } from "./idp-connection-CHxGm1Wr.mjs";
2
+ //#region src/idp/provider.ts
3
+ /**
4
+ * The variables a connection scaffolded under `slug` references.
5
+ *
6
+ * Derived from the slug rather than the provider: a Project may hold a second
7
+ * connection for the same provider under a slug of its own, and its
8
+ * credentials belong to that connection, not to the provider.
9
+ */
10
+ function credentialVariables(slug) {
11
+ return {
12
+ clientId: credentialVariable(slug, "CLIENT_ID"),
13
+ clientSecret: credentialVariable(slug, "CLIENT_SECRET")
14
+ };
15
+ }
16
+ /**
17
+ * A credential's variable name: the slug uppercased with every non-alphanumeric
18
+ * replaced by `_`, then the suffix. A slug may start with a digit, which no
19
+ * shell accepts as the first character of a name, so such a name gains a `_`.
20
+ */
21
+ function credentialVariable(slug, suffix) {
22
+ const name = `${slug.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_${suffix}`;
23
+ return /^[0-9]/.test(name) ? `_${name}` : name;
24
+ }
25
+ /**
26
+ * The `${{ NAME }}` reference written to a credential field, as
27
+ * `idp-connection.json` requires: a whole-value placeholder, with no text
28
+ * around it that would be rendered into the resolved credential.
29
+ */
30
+ function variableReference(name) {
31
+ return `\${{ ${name} }}`;
32
+ }
33
+ /**
34
+ * The variable a `${{ NAME }}` reference names, or `undefined` when the value
35
+ * is not one.
36
+ *
37
+ * A connection is editable, so the name it references need not be the one this
38
+ * CLI would have chosen — a hand-written file may point at `ACME_SECRET`.
39
+ * Publishing to a name derived from the slug instead would store the credential
40
+ * where nothing reads it and report success.
41
+ */
42
+ function referencedVariable(value) {
43
+ return /^\$\{\{ *(\w+) *\}\}$/.exec(value.trim())?.[1];
44
+ }
45
+ /** Whether a stored value is a reference rather than a credential. */
46
+ function isVariableReference(value) {
47
+ return referencedVariable(value) !== void 0;
48
+ }
49
+ //#endregion
50
+ //#region src/idp/oidc-provider.ts
51
+ /**
52
+ * The parts of a connection document every OIDC provider composes the same way.
53
+ *
54
+ * A subclass supplies what is genuinely its own — the vendor's identity, its
55
+ * issuer, its claim table, and any protocol settings it needs — and inherits
56
+ * the composition. Nothing here knows about a specific vendor, so a provider
57
+ * whose document is shaped differently overrides rather than adds a branch.
58
+ */
59
+ var OidcProvider = class {
60
+ /** The claim that carries the provider's stable, unique id for an account. */
61
+ subjectClaim = "sub";
62
+ /**
63
+ * Schema property name → how its value is verified: a claim to read, `true`
64
+ * for a provider trusted outright, or `"$supplementary_fetch"`.
65
+ *
66
+ * Keyed by schema property, like {@link claimTable}, so it narrows with it.
67
+ */
68
+ verifiedClaims = {};
69
+ /** Parameters the vendor wants on every authorization request. */
70
+ staticAuthorizeParameters = {};
71
+ claimMapping(schemaProperties) {
72
+ const defined = new Set(schemaProperties);
73
+ return Object.fromEntries(Object.entries(this.claimTable).filter(([property]) => defined.has(property)));
74
+ }
75
+ /**
76
+ * Compose the connection document. Pure: it returns the object the caller
77
+ * writes to `.zitadel/idps/<slug>.json`, and performs no IO.
78
+ *
79
+ * Neither credential is written into it. Both are `${{ NAME }}` references to
80
+ * project variables: the secret because the document is committed and a
81
+ * revision is immutable, so a literal could never be scrubbed; the id because
82
+ * each environment registers its own application, and a literal would force
83
+ * one connection file per environment.
84
+ *
85
+ * Endpoints are named only when the connection points somewhere other than
86
+ * the vendor, and then only the issuer. The engine accepts a connection
87
+ * naming every endpoint or none, and it needs four — so a subset is rejected,
88
+ * and a stand-in serves its own discovery document as the vendor does.
89
+ */
90
+ connection(options) {
91
+ const slug = options.slug ?? this.slug;
92
+ const claimMapping = this.claimMapping(options.schemaProperties);
93
+ const verifiedClaims = Object.fromEntries(Object.entries(this.verifiedClaims).filter(([property]) => property in claimMapping));
94
+ const issuer = options.endpoints?.issuer;
95
+ const variables = credentialVariables(slug);
96
+ return {
97
+ ...options.schemaRef ? { $schema: options.schemaRef } : {},
98
+ slug,
99
+ protocol: "oidc",
100
+ template: this.template,
101
+ display_name: this.displayName,
102
+ subject_claim: this.subjectClaim,
103
+ ...Object.keys(verifiedClaims).length > 0 ? { verified_claims: verifiedClaims } : {},
104
+ ...Object.keys(claimMapping).length > 0 ? { claim_mapping: claimMapping } : {},
105
+ provisioning: { creation: "auto" },
106
+ oidc: {
107
+ issuer: issuer !== void 0 && issuer !== "" ? issuer : this.issuer,
108
+ scopes: [...this.scopes],
109
+ ...Object.keys(this.staticAuthorizeParameters).length > 0 ? { static_authorize_parameters: { ...this.staticAuthorizeParameters } } : {},
110
+ client_id: variableReference(variables.clientId),
111
+ client_secret: variableReference(variables.clientSecret)
112
+ }
113
+ };
114
+ }
115
+ };
116
+ //#endregion
117
+ //#region src/idp/google.ts
118
+ /**
119
+ * Google, as `zitadel setup` and `sso enable` scaffold it.
120
+ *
121
+ * Everything here is Google's own documented behaviour, cross-checked against
122
+ * its discovery document and the provider packages in zitadel/zitadel. It names
123
+ * no endpoints: Google publishes a discovery document, its endpoints do not
124
+ * share the issuer's host, and the engine resolves them at runtime — so a value
125
+ * committed here would be a guess that ages.
126
+ */
127
+ var GoogleProvider = class extends OidcProvider {
128
+ slug = "google";
129
+ displayName = "Google";
130
+ template = "google";
131
+ consoleUrl = "https://console.cloud.google.com/apis/credentials";
132
+ docsUrl = "https://developers.google.com/identity/openid-connect/openid-connect";
133
+ /** One client takes many redirect URIs, so one application serves every environment. */
134
+ callbackGuidance = "multi_uri_client";
135
+ issuer = "https://accounts.google.com";
136
+ claimTable = {
137
+ email: "email",
138
+ givenName: "given_name",
139
+ familyName: "family_name"
140
+ };
141
+ scopes = [
142
+ "openid",
143
+ "profile",
144
+ "email"
145
+ ];
146
+ /** `sub` never changes, unlike an email, so identity keys on it. */
147
+ subjectClaim = "sub";
148
+ verifiedClaims = { email: "email_verified" };
149
+ /** Google reuses a signed-in session silently without it. */
150
+ staticAuthorizeParameters = { prompt: "select_account" };
151
+ };
152
+ //#endregion
153
+ //#region src/idp/issuer.ts
154
+ /**
155
+ * The issuer values a connection may name: HTTPS anywhere, or HTTP on
156
+ * `localhost`/`127.0.0.1` for a local stand-in.
157
+ *
158
+ * Read out of the generated meta-schema rather than restated here, so a prompt
159
+ * that accepts a value and the document written from it cannot disagree. That
160
+ * file is generated from the OpenAPI YAML the server embeds, which makes it
161
+ * also what the server will enforce — `http://idp.internal:9100` would be
162
+ * taken by a hand-rolled URL check and then rejected on apply.
163
+ */
164
+ function issuerPattern() {
165
+ const pattern = ((idp_connection_default.properties?.oidc)?.properties?.issuer)?.pattern;
166
+ if (typeof pattern !== "string") throw new Error("idp-connection.json no longer states properties.oidc.properties.issuer.pattern");
167
+ return new RegExp(pattern);
168
+ }
169
+ let compiled;
170
+ /** Whether a connection may name this issuer. */
171
+ function isSupportedIssuer(value) {
172
+ compiled ??= issuerPattern();
173
+ return compiled.test(value.trim());
174
+ }
175
+ /** What to tell someone who typed an issuer the contract does not allow. */
176
+ const ISSUER_REQUIREMENT = "Use an https:// URL, or http:// on localhost or 127.0.0.1.";
177
+ //#endregion
178
+ //#region src/idp/index.ts
179
+ /**
180
+ * The providers `zitadel setup` and `sso enable` can scaffold a connection for.
181
+ *
182
+ * Adding one means adding a class and listing it here. That is a code change
183
+ * rather than a data change, which is the point: a provider is not only a table
184
+ * of values, and the ones that differ — OAuth2 rather than OIDC, a second
185
+ * request to read an email, a claim the vendor does not emit — differ in
186
+ * behaviour. Holding that in the provider keeps it out of the callers.
187
+ */
188
+ const PROVIDERS = Object.freeze([new GoogleProvider()]);
189
+ const BY_SLUG = new Map(PROVIDERS.map((provider) => [provider.slug, provider]));
190
+ /** Every provider's slug, in listing order. The `--provider` flag takes one. */
191
+ const IDP_PROVIDERS = Object.freeze(PROVIDERS.map((provider) => provider.slug));
192
+ /**
193
+ * One provider by slug.
194
+ *
195
+ * Throws rather than returning `undefined`: every caller has already had the
196
+ * slug validated against {@link IDP_PROVIDERS}, so a miss here is a bug in this
197
+ * package and not something a caller can act on.
198
+ */
199
+ function idpProvider(slug) {
200
+ const provider = BY_SLUG.get(slug);
201
+ if (provider === void 0) throw new Error(`unknown identity provider ${JSON.stringify(slug)} (known providers: ${IDP_PROVIDERS.join(", ")})`);
202
+ return provider;
203
+ }
204
+ //#endregion
205
+ export { GoogleProvider as a, credentialVariables as c, variableReference as d, isSupportedIssuer as i, isVariableReference as l, idpProvider as n, OidcProvider as o, ISSUER_REQUIREMENT as r, credentialVariable as s, IDP_PROVIDERS as t, referencedVariable as u };
206
+
207
+ //# sourceMappingURL=idp-ByzXQN85.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idp-ByzXQN85.mjs","names":["idpConnectionMetaSchema"],"sources":["../src/idp/provider.ts","../src/idp/oidc-provider.ts","../src/idp/google.ts","../src/idp/issuer.ts","../src/idp/index.ts"],"sourcesContent":["/**\n * What the CLI needs to know about one identity provider to scaffold a working\n * connection for it: how to name it, where to send the developer to register an\n * application, and how to compose the connection document.\n *\n * One class per provider, because a provider is not only a table of values.\n * Google is pure data today; GitHub speaks OAuth2 rather than OIDC, has no\n * family-name claim, and needs a second request to read an email at all. A\n * shape that only holds data forces that behaviour somewhere else, where it\n * stops being the provider's business and starts being a branch in shared code.\n */\n\n/**\n * Whether the vendor accepts many redirect URIs on a single client, or needs a\n * separate application per environment. Surfaced when the developer is told\n * what to register, so they register the right thing.\n */\nexport type CallbackGuidance = \"multi_uri_client\" | \"app_per_environment\";\n\n/** Where a connection points, when not at the vendor. */\nexport type ConnectionEndpoints = {\n readonly issuer?: string;\n};\n\n/** What a connection document needs beyond the provider's own knowledge. */\nexport type ScaffoldOptions = {\n /** Properties the target user schema defines, which bounds the claim mapping. */\n readonly schemaProperties: Iterable<string>;\n /** Slug to write under; defaults to the provider's own. */\n readonly slug?: string;\n /** `$schema` pointer, relative to `.zitadel/idps/`. */\n readonly schemaRef?: string;\n /** Point the connection somewhere other than the vendor (local testing). */\n readonly endpoints?: ConnectionEndpoints;\n};\n\nexport interface IdpProvider {\n /** Default connection slug, and the name `--provider` takes. */\n readonly slug: string;\n /** Written to the connection and shown on the sign-in button. */\n readonly displayName: string;\n /**\n * Written to the connection as `template`. Keys vendor knowledge only —\n * glyphs, button branding, the setup scan — and carries no protocol\n * behaviour.\n */\n readonly template: string;\n /** Where the developer registers the application. */\n readonly consoleUrl: string;\n /** The vendor's own integration documentation. */\n readonly docsUrl: string;\n readonly callbackGuidance: CallbackGuidance;\n /** The issuer the vendor publishes, and the default when one is asked for. */\n readonly issuer: string;\n /**\n * The claims this provider emits, keyed by schema property name, narrowed to\n * the properties the target schema actually defines.\n */\n claimMapping(schemaProperties: Iterable<string>): Record<string, string>;\n /** The document `zitadel setup` writes to `.zitadel/idps/<slug>.json`. */\n connection(options: ScaffoldOptions): Record<string, unknown>;\n}\n\n/** The project variables a connection's two credentials reference. */\nexport type CredentialVariables = {\n readonly clientId: string;\n readonly clientSecret: string;\n};\n\n/**\n * The variables a connection scaffolded under `slug` references.\n *\n * Derived from the slug rather than the provider: a Project may hold a second\n * connection for the same provider under a slug of its own, and its\n * credentials belong to that connection, not to the provider.\n */\nexport function credentialVariables(slug: string): CredentialVariables {\n return {\n clientId: credentialVariable(slug, \"CLIENT_ID\"),\n clientSecret: credentialVariable(slug, \"CLIENT_SECRET\"),\n };\n}\n\n/**\n * A credential's variable name: the slug uppercased with every non-alphanumeric\n * replaced by `_`, then the suffix. A slug may start with a digit, which no\n * shell accepts as the first character of a name, so such a name gains a `_`.\n */\nexport function credentialVariable(slug: string, suffix: string): string {\n const name = `${slug.toUpperCase().replace(/[^A-Z0-9]/g, \"_\")}_${suffix}`;\n return /^[0-9]/.test(name) ? `_${name}` : name;\n}\n\n/**\n * The `${{ NAME }}` reference written to a credential field, as\n * `idp-connection.json` requires: a whole-value placeholder, with no text\n * around it that would be rendered into the resolved credential.\n */\nexport function variableReference(name: string): string {\n return `\\${{ ${name} }}`;\n}\n\n/**\n * The variable a `${{ NAME }}` reference names, or `undefined` when the value\n * is not one.\n *\n * A connection is editable, so the name it references need not be the one this\n * CLI would have chosen — a hand-written file may point at `ACME_SECRET`.\n * Publishing to a name derived from the slug instead would store the credential\n * where nothing reads it and report success.\n */\nexport function referencedVariable(value: string): string | undefined {\n return /^\\$\\{\\{ *(\\w+) *\\}\\}$/.exec(value.trim())?.[1];\n}\n\n/** Whether a stored value is a reference rather than a credential. */\nexport function isVariableReference(value: string): boolean {\n return referencedVariable(value) !== undefined;\n}\n","import {\n credentialVariables,\n variableReference,\n type CallbackGuidance,\n type IdpProvider,\n type ScaffoldOptions,\n} from \"./provider.js\";\n\n/**\n * The parts of a connection document every OIDC provider composes the same way.\n *\n * A subclass supplies what is genuinely its own — the vendor's identity, its\n * issuer, its claim table, and any protocol settings it needs — and inherits\n * the composition. Nothing here knows about a specific vendor, so a provider\n * whose document is shaped differently overrides rather than adds a branch.\n */\nexport abstract class OidcProvider implements IdpProvider {\n abstract readonly slug: string;\n abstract readonly displayName: string;\n abstract readonly template: string;\n abstract readonly consoleUrl: string;\n abstract readonly docsUrl: string;\n abstract readonly callbackGuidance: CallbackGuidance;\n abstract readonly issuer: string;\n\n /**\n * Schema property name → the claim this provider documents for it.\n *\n * Authored per provider rather than derived: each row pairs a property with\n * the vendor's documented claim name, and a wrong one fails silently — the\n * claim is never found and the property stays unmapped.\n */\n protected abstract readonly claimTable: Readonly<Record<string, string>>;\n\n /** Scopes the connection requests. */\n protected abstract readonly scopes: readonly string[];\n\n /** The claim that carries the provider's stable, unique id for an account. */\n protected readonly subjectClaim: string = \"sub\";\n\n /**\n * Schema property name → how its value is verified: a claim to read, `true`\n * for a provider trusted outright, or `\"$supplementary_fetch\"`.\n *\n * Keyed by schema property, like {@link claimTable}, so it narrows with it.\n */\n protected readonly verifiedClaims: Readonly<Record<string, string | true>> = {};\n\n /** Parameters the vendor wants on every authorization request. */\n protected readonly staticAuthorizeParameters: Readonly<Record<string, string>> = {};\n\n claimMapping(schemaProperties: Iterable<string>): Record<string, string> {\n const defined = new Set(schemaProperties);\n return Object.fromEntries(\n Object.entries(this.claimTable).filter(([property]) => defined.has(property)),\n );\n }\n\n /**\n * Compose the connection document. Pure: it returns the object the caller\n * writes to `.zitadel/idps/<slug>.json`, and performs no IO.\n *\n * Neither credential is written into it. Both are `${{ NAME }}` references to\n * project variables: the secret because the document is committed and a\n * revision is immutable, so a literal could never be scrubbed; the id because\n * each environment registers its own application, and a literal would force\n * one connection file per environment.\n *\n * Endpoints are named only when the connection points somewhere other than\n * the vendor, and then only the issuer. The engine accepts a connection\n * naming every endpoint or none, and it needs four — so a subset is rejected,\n * and a stand-in serves its own discovery document as the vendor does.\n */\n connection(options: ScaffoldOptions): Record<string, unknown> {\n const slug = options.slug ?? this.slug;\n const claimMapping = this.claimMapping(options.schemaProperties);\n // Verification is of a mapped value, so it narrows to what was mapped: a\n // schema without `email` gets no email mapping, and an `email` entry here\n // would then claim to verify a value this connection never supplies.\n const verifiedClaims = Object.fromEntries(\n Object.entries(this.verifiedClaims).filter(([property]) => property in claimMapping),\n );\n const issuer = options.endpoints?.issuer;\n const variables = credentialVariables(slug);\n return {\n ...(options.schemaRef ? { $schema: options.schemaRef } : {}),\n slug,\n protocol: \"oidc\",\n template: this.template,\n display_name: this.displayName,\n subject_claim: this.subjectClaim,\n ...(Object.keys(verifiedClaims).length > 0 ? { verified_claims: verifiedClaims } : {}),\n ...(Object.keys(claimMapping).length > 0 ? { claim_mapping: claimMapping } : {}),\n provisioning: { creation: \"auto\" },\n oidc: {\n issuer: issuer !== undefined && issuer !== \"\" ? issuer : this.issuer,\n scopes: [...this.scopes],\n ...(Object.keys(this.staticAuthorizeParameters).length > 0\n ? { static_authorize_parameters: { ...this.staticAuthorizeParameters } }\n : {}),\n client_id: variableReference(variables.clientId),\n client_secret: variableReference(variables.clientSecret),\n },\n };\n }\n}\n","import { OidcProvider } from \"./oidc-provider.js\";\nimport type { CallbackGuidance } from \"./provider.js\";\n\n/**\n * Google, as `zitadel setup` and `sso enable` scaffold it.\n *\n * Everything here is Google's own documented behaviour, cross-checked against\n * its discovery document and the provider packages in zitadel/zitadel. It names\n * no endpoints: Google publishes a discovery document, its endpoints do not\n * share the issuer's host, and the engine resolves them at runtime — so a value\n * committed here would be a guess that ages.\n */\nexport class GoogleProvider extends OidcProvider {\n readonly slug = \"google\";\n readonly displayName = \"Google\";\n readonly template = \"google\";\n readonly consoleUrl = \"https://console.cloud.google.com/apis/credentials\";\n readonly docsUrl = \"https://developers.google.com/identity/openid-connect/openid-connect\";\n /** One client takes many redirect URIs, so one application serves every environment. */\n readonly callbackGuidance: CallbackGuidance = \"multi_uri_client\";\n readonly issuer = \"https://accounts.google.com\";\n\n protected readonly claimTable = {\n email: \"email\",\n givenName: \"given_name\",\n familyName: \"family_name\",\n };\n\n protected readonly scopes = [\"openid\", \"profile\", \"email\"];\n\n /** `sub` never changes, unlike an email, so identity keys on it. */\n protected override readonly subjectClaim = \"sub\";\n\n protected override readonly verifiedClaims = { email: \"email_verified\" };\n\n /** Google reuses a signed-in session silently without it. */\n protected override readonly staticAuthorizeParameters = { prompt: \"select_account\" };\n}\n","import idpConnectionMetaSchema from \"../../meta-schemas/idp-connection.json\" with { type: \"json\" };\n\n/**\n * The issuer values a connection may name: HTTPS anywhere, or HTTP on\n * `localhost`/`127.0.0.1` for a local stand-in.\n *\n * Read out of the generated meta-schema rather than restated here, so a prompt\n * that accepts a value and the document written from it cannot disagree. That\n * file is generated from the OpenAPI YAML the server embeds, which makes it\n * also what the server will enforce — `http://idp.internal:9100` would be\n * taken by a hand-rolled URL check and then rejected on apply.\n */\nfunction issuerPattern(): RegExp {\n const oidc = (idpConnectionMetaSchema as { properties?: Record<string, unknown> }).properties\n ?.oidc;\n const issuer = (oidc as { properties?: Record<string, unknown> } | undefined)?.properties?.issuer;\n const pattern = (issuer as { pattern?: unknown } | undefined)?.pattern;\n if (typeof pattern !== \"string\") {\n // Silently accepting everything would be the worst outcome: the prompt\n // would go on reporting success for connections the server refuses.\n throw new Error(\n \"idp-connection.json no longer states properties.oidc.properties.issuer.pattern\",\n );\n }\n return new RegExp(pattern);\n}\n\nlet compiled: RegExp | undefined;\n\n/** Whether a connection may name this issuer. */\nexport function isSupportedIssuer(value: string): boolean {\n compiled ??= issuerPattern();\n return compiled.test(value.trim());\n}\n\n/** What to tell someone who typed an issuer the contract does not allow. */\nexport const ISSUER_REQUIREMENT = \"Use an https:// URL, or http:// on localhost or 127.0.0.1.\";\n","/**\n * The providers `zitadel setup` and `sso enable` can scaffold a connection for.\n *\n * Adding one means adding a class and listing it here. That is a code change\n * rather than a data change, which is the point: a provider is not only a table\n * of values, and the ones that differ — OAuth2 rather than OIDC, a second\n * request to read an email, a claim the vendor does not emit — differ in\n * behaviour. Holding that in the provider keeps it out of the callers.\n */\nimport { GoogleProvider } from \"./google.js\";\nimport type { IdpProvider } from \"./provider.js\";\n\nconst PROVIDERS: readonly IdpProvider[] = Object.freeze([new GoogleProvider()]);\n\nconst BY_SLUG: ReadonlyMap<string, IdpProvider> = new Map(\n PROVIDERS.map((provider) => [provider.slug, provider]),\n);\n\n/** Every provider's slug, in listing order. The `--provider` flag takes one. */\nexport const IDP_PROVIDERS: readonly string[] = Object.freeze(\n PROVIDERS.map((provider) => provider.slug),\n);\n\n/**\n * One provider by slug.\n *\n * Throws rather than returning `undefined`: every caller has already had the\n * slug validated against {@link IDP_PROVIDERS}, so a miss here is a bug in this\n * package and not something a caller can act on.\n */\nexport function idpProvider(slug: string): IdpProvider {\n const provider = BY_SLUG.get(slug);\n if (provider === undefined) {\n throw new Error(\n `unknown identity provider ${JSON.stringify(slug)} (known providers: ${IDP_PROVIDERS.join(\", \")})`,\n );\n }\n return provider;\n}\n\nexport { ISSUER_REQUIREMENT, isSupportedIssuer } from \"./issuer.js\";\n\nexport { GoogleProvider } from \"./google.js\";\nexport { OidcProvider } from \"./oidc-provider.js\";\nexport {\n credentialVariable,\n credentialVariables,\n isVariableReference,\n referencedVariable,\n variableReference,\n type CallbackGuidance,\n type ConnectionEndpoints,\n type CredentialVariables,\n type IdpProvider,\n type ScaffoldOptions,\n} from \"./provider.js\";\n"],"mappings":"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"}
@@ -0,0 +1,324 @@
1
+ //#region meta-schemas/idp-connection.json
2
+ var idp_connection_default = {
3
+ $comment: "Code generated by scripts/generate-meta-schemas.ts; DO NOT EDIT.",
4
+ $schema: "https://json-schema.org/draft/2020-12/schema",
5
+ title: "IdentityProviderConnection",
6
+ type: "object",
7
+ required: [
8
+ "slug",
9
+ "protocol",
10
+ "display_name"
11
+ ],
12
+ additionalProperties: false,
13
+ properties: {
14
+ "$schema": {
15
+ "type": "string",
16
+ "minLength": 1,
17
+ "description": "Editor affordance: path or URL of this schema so editors validate and autocomplete the file (scaffolded connection files point at `.zitadel/meta/idp-connection.json`). Ignored by the platform."
18
+ },
19
+ "slug": {
20
+ "type": "string",
21
+ "pattern": "^[a-z0-9][a-z0-9_-]*$",
22
+ "maxLength": 64,
23
+ "description": "Stable identifier, referenced by user schemas (x-auth-methods.sso.providers) and flow steps (sso_providers). Unique within the Project.",
24
+ "examples": [
25
+ "google",
26
+ "github",
27
+ "corp_idp"
28
+ ]
29
+ },
30
+ "protocol": {
31
+ "type": "string",
32
+ "enum": ["oidc", "oauth2"],
33
+ "description": "The protocol used by the identity provider."
34
+ },
35
+ "template": {
36
+ "type": "string",
37
+ "examples": [
38
+ "google",
39
+ "github",
40
+ "okta"
41
+ ],
42
+ "description": "Template hint for rendering the provider (logo, colors). Carries no protocol behavior: conduct comes only from the protocol blocks."
43
+ },
44
+ "display_name": {
45
+ "type": "string",
46
+ "minLength": 1,
47
+ "maxLength": 256,
48
+ "description": "Shown to the user on the sign-in button."
49
+ },
50
+ "subject_claim": {
51
+ "type": "string",
52
+ "minLength": 1,
53
+ "description": "Claim carrying the provider's stable subject identifier. Optional for OIDC (the engine uses `sub` per spec; override where `sub` is pairwise, e.g. Entra `oid`). Required for OAuth2 — no `sub` guarantee."
54
+ },
55
+ "claim_mapping": {
56
+ "type": "object",
57
+ "additionalProperties": {
58
+ "type": "string",
59
+ "pattern": "^[^$]"
60
+ },
61
+ "description": "Maps user-schema property names (keys) to provider claim names (values). A value is an exact top-level claim key: no path syntax, and a dot is part of the key, so nested claims (OIDC `address`, GitHub `plan`) are not addressable yet. `$`-prefixed strings and non-string values are reserved for future mapping forms. Add properties defined in the user schemas; unmatched entries are ignored."
62
+ },
63
+ "verified_claims": {
64
+ "type": "object",
65
+ "additionalProperties": { "anyOf": [
66
+ { "const": true },
67
+ { "const": "$supplementary_fetch" },
68
+ {
69
+ "type": "string",
70
+ "pattern": "^[^$]"
71
+ }
72
+ ] },
73
+ "description": "Maps a verifiable user-schema property to its verification source: a claim name (read the claim), the literal `true` (trust this provider unconditionally), or the `$`-pointer `\"$supplementary_fetch\"` (verified by the selected supplementary_fetch strategy per its contract - e.g. github_primary_email verifies `email` via primary && verified). Values starting with `$` are reserved; only `$supplementary_fetch` is defined. Distinct from claim_mapping, which carries values, not verification state.",
74
+ "examples": [
75
+ { "email": "email_verified" },
76
+ { "email": true },
77
+ { "email": "$supplementary_fetch" }
78
+ ]
79
+ },
80
+ "provisioning": {
81
+ "type": "object",
82
+ "additionalProperties": false,
83
+ "description": "How far this provider's data is trusted. `creation` defines what happens to a subject that has no account yet. With `disabled`, a user is not created. With `auto`, the user is created without a collection step when the mapped claims fill every required property of the schema. A required property with an `x-unique` scope must also arrive verified according to `verified_claims`. When a required property is missing or such a property is unverified, the collection step is shown instead, prefilled with the claims. Gating on other properties will be added when `x-verify` returns to the dialect. The following are deferred and will be added as additive changes. The `auto_only` value creates the user from complete claims or fails without collecting. The linking policy (`is_linking_allowed`, `auto_linking`), together with the account-linking journey. `is_auto_update`, together with per-property verification state.",
84
+ "properties": { "creation": {
85
+ "type": "string",
86
+ "enum": ["disabled", "auto"],
87
+ "default": "auto"
88
+ } }
89
+ },
90
+ "oidc": {
91
+ "type": "object",
92
+ "additionalProperties": false,
93
+ "description": "OIDC connection details. Endpoints come from the issuer's discovery document. A provider that exposes no .well-known document names them all instead: authorization_endpoint, token_endpoint, jwks_uri, and userinfo_endpoint unless id_token_mapping is set. Setting some but not all is rejected.",
94
+ "required": [
95
+ "issuer",
96
+ "client_id",
97
+ "client_secret",
98
+ "scopes"
99
+ ],
100
+ "properties": {
101
+ "issuer": {
102
+ "type": "string",
103
+ "format": "uri",
104
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)(/[^\\s?#]*)?$",
105
+ "description": "Discovery base. Endpoints are resolved from its .well-known document unless the connection names them all."
106
+ },
107
+ "jwks_uri": {
108
+ "type": "string",
109
+ "format": "uri",
110
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)([/?][^\\s#]*)?$",
111
+ "description": "JWKS endpoint, for a provider that exposes no .well-known document. Set together with the other endpoints."
112
+ },
113
+ "id_token_mapping": {
114
+ "type": "boolean",
115
+ "default": false,
116
+ "description": "Read user claims from the id_token instead of the userinfo endpoint, for providers that populate only the former."
117
+ },
118
+ "authorization_endpoint": {
119
+ "type": "string",
120
+ "format": "uri",
121
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)([/?][^\\s#]*)?$",
122
+ "description": "For a provider that exposes no .well-known document. Set together with the other endpoints."
123
+ },
124
+ "token_endpoint": {
125
+ "type": "string",
126
+ "format": "uri",
127
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)([/?][^\\s#]*)?$",
128
+ "description": "For a provider that exposes no .well-known document. Set together with the other endpoints."
129
+ },
130
+ "userinfo_endpoint": {
131
+ "type": "string",
132
+ "format": "uri",
133
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)([/?][^\\s#]*)?$",
134
+ "description": "For a provider that exposes no .well-known document. Set together with the other endpoints; not needed when id_token_mapping is set."
135
+ },
136
+ "client_id": {
137
+ "type": "string",
138
+ "minLength": 1,
139
+ "maxLength": 512,
140
+ "description": "Either a literal in case the same client is used in all environments, or a `${{ NAME }}` reference to a variable in case of separate clients per environment."
141
+ },
142
+ "client_secret": {
143
+ "type": "string",
144
+ "pattern": "^\\$\\{\\{ *[A-Za-z0-9_]+ *\\}\\}$",
145
+ "description": "A reference to the variable holding the client secret, never the secret itself. A secret may only be referenced as the entire value: text around the placeholder would be rendered into the resolved credential, so it is rejected. The engine resolves it against the environment serving the request."
146
+ },
147
+ "token_endpoint_auth_method": {
148
+ "type": "string",
149
+ "enum": ["client_secret_basic", "client_secret_post"],
150
+ "default": "client_secret_basic",
151
+ "description": "How the client authenticates at the token endpoint."
152
+ },
153
+ "scopes": {
154
+ "type": "array",
155
+ "items": {
156
+ "type": "string",
157
+ "minLength": 1
158
+ },
159
+ "uniqueItems": true,
160
+ "minItems": 1,
161
+ "contains": { "const": "openid" },
162
+ "default": [
163
+ "openid",
164
+ "profile",
165
+ "email"
166
+ ],
167
+ "description": "Must contain `openid` - without it the provider returns no id_token and the connection is not OIDC. Enforced by `required` + `contains`; the `default` is a UI-prefill hint only - validators never inject it, so an omitted `scopes` is rejected regardless."
168
+ },
169
+ "pkce_enabled": {
170
+ "type": "boolean",
171
+ "default": true,
172
+ "description": "Send PKCE (code_challenge/code_verifier). Providers that do not support PKCE typically ignore the parameters, so `true` is safe and future-proofs; set `false` only for a provider whose token endpoint rejects them."
173
+ },
174
+ "static_authorize_parameters": {
175
+ "type": "object",
176
+ "propertyNames": {
177
+ "minLength": 1,
178
+ "not": { "enum": [
179
+ "client_id",
180
+ "redirect_uri",
181
+ "response_type",
182
+ "scope",
183
+ "state",
184
+ "nonce",
185
+ "code_challenge",
186
+ "code_challenge_method",
187
+ "response_mode",
188
+ "request",
189
+ "request_uri",
190
+ "client_secret",
191
+ "client_assertion"
192
+ ] }
193
+ },
194
+ "additionalProperties": { "type": "string" },
195
+ "description": "Extra provider-specific authorize parameters (for example `prompt`). Engine-owned protocol parameters are reserved and rejected by `propertyNames`: the engine composes them itself, and an override of `state` or `nonce` would silently defeat CSRF and token binding. `client_secret` and `client_assertion` are rejected as they could be appended to the public authorize URL."
196
+ }
197
+ }
198
+ },
199
+ "oauth2": {
200
+ "type": "object",
201
+ "additionalProperties": false,
202
+ "description": "OAuth 2.0 connection details.",
203
+ "required": [
204
+ "authorization_endpoint",
205
+ "token_endpoint",
206
+ "userinfo_endpoint",
207
+ "client_id",
208
+ "client_secret"
209
+ ],
210
+ "properties": {
211
+ "authorization_endpoint": {
212
+ "type": "string",
213
+ "format": "uri",
214
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)([/?][^\\s#]*)?$",
215
+ "description": "Where the user is sent to authorize."
216
+ },
217
+ "token_endpoint": {
218
+ "type": "string",
219
+ "format": "uri",
220
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)([/?][^\\s#]*)?$",
221
+ "description": "Where the authorization code is exchanged."
222
+ },
223
+ "userinfo_endpoint": {
224
+ "type": "string",
225
+ "format": "uri",
226
+ "pattern": "^(https://[^\\s/?#]+|http://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?)([/?][^\\s#]*)?$",
227
+ "description": "Where the authenticated user's profile is fetched."
228
+ },
229
+ "client_id": {
230
+ "type": "string",
231
+ "minLength": 1,
232
+ "maxLength": 512,
233
+ "description": "Either a literal in case the same client is used in all environments, or a `${{ NAME }}` reference to a variable in case of separate clients per environment."
234
+ },
235
+ "client_secret": {
236
+ "type": "string",
237
+ "pattern": "^\\$\\{\\{ *[A-Za-z0-9_]+ *\\}\\}$",
238
+ "description": "A reference to the variable holding the client secret, never the secret itself. A secret may only be referenced as the entire value: text around the placeholder would be rendered into the resolved credential, so it is rejected. The engine resolves it against the environment serving the request."
239
+ },
240
+ "token_endpoint_auth_method": {
241
+ "type": "string",
242
+ "enum": ["client_secret_basic", "client_secret_post"],
243
+ "default": "client_secret_basic",
244
+ "description": "How the client authenticates at the token endpoint."
245
+ },
246
+ "scopes": {
247
+ "type": "array",
248
+ "items": {
249
+ "type": "string",
250
+ "minLength": 1
251
+ },
252
+ "uniqueItems": true,
253
+ "description": "Provider-specific; OAuth 2.0 defines no universal scope."
254
+ },
255
+ "pkce_enabled": {
256
+ "type": "boolean",
257
+ "default": true,
258
+ "description": "Send PKCE (code_challenge/code_verifier). Providers that do not support PKCE typically ignore the parameters, so `true` is safe and future-proofs; set `false` only for a provider whose token endpoint rejects them."
259
+ },
260
+ "static_authorize_parameters": {
261
+ "type": "object",
262
+ "propertyNames": {
263
+ "minLength": 1,
264
+ "not": { "enum": [
265
+ "client_id",
266
+ "redirect_uri",
267
+ "response_type",
268
+ "scope",
269
+ "state",
270
+ "nonce",
271
+ "code_challenge",
272
+ "code_challenge_method",
273
+ "response_mode",
274
+ "request",
275
+ "request_uri",
276
+ "client_secret",
277
+ "client_assertion"
278
+ ] }
279
+ },
280
+ "additionalProperties": { "type": "string" },
281
+ "description": "Extra provider-specific authorize parameters (for example `prompt`). Engine-owned protocol parameters are reserved and rejected by `propertyNames`: the engine composes them itself, and an override of `state` or `nonce` would silently defeat CSRF and token binding. `client_secret` and `client_assertion` are rejected as they could be appended to the public authorize URL."
282
+ },
283
+ "supplementary_fetch": {
284
+ "type": "string",
285
+ "enum": ["github_primary_email"],
286
+ "description": "Provider-specific follow-up call after userinfo. New values are non-breaking."
287
+ }
288
+ },
289
+ "allOf": [{
290
+ "if": {
291
+ "properties": { "supplementary_fetch": { "const": "github_primary_email" } },
292
+ "required": ["supplementary_fetch"]
293
+ },
294
+ "then": {
295
+ "required": ["scopes"],
296
+ "properties": { "scopes": { "contains": { "const": "user:email" } } }
297
+ }
298
+ }]
299
+ }
300
+ },
301
+ allOf: [{
302
+ "if": {
303
+ "properties": { "protocol": { "const": "oidc" } },
304
+ "required": ["protocol"]
305
+ },
306
+ "then": {
307
+ "required": ["oidc"],
308
+ "properties": { "oauth2": false }
309
+ }
310
+ }, {
311
+ "if": {
312
+ "properties": { "protocol": { "const": "oauth2" } },
313
+ "required": ["protocol"]
314
+ },
315
+ "then": {
316
+ "required": ["oauth2", "subject_claim"],
317
+ "properties": { "oidc": false }
318
+ }
319
+ }]
320
+ };
321
+ //#endregion
322
+ export { idp_connection_default as t };
323
+
324
+ //# sourceMappingURL=idp-connection-CHxGm1Wr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idp-connection-CHxGm1Wr.mjs","names":[],"sources":["../meta-schemas/idp-connection.json"],"sourcesContent":[""],"mappings":""}