Skip to content

[CONTENT SPRINT] Identity Stack Cookbook: Auth0, Okta, Entra ID, and Keycloak#189

Closed
CamSoper wants to merge 4 commits into
masterfrom
compare/pr-18962
Closed

[CONTENT SPRINT] Identity Stack Cookbook: Auth0, Okta, Entra ID, and Keycloak#189
CamSoper wants to merge 4 commits into
masterfrom
compare/pr-18962

Conversation

@CamSoper
Copy link
Copy Markdown
Owner

Pipeline test fixture. Mirrors pulumi/docs#18962 at upstream HEAD a9474fefdb, captured 2026-05-15. Cherry-picked onto cam-fork master with the post-S49 pipeline architecture in place. The pipeline review on this PR is the test signal; don't merge this fixture.


Upstream PR body

Why this content is interesting

  • It compares real identity provider patterns across Auth0, Okta, Microsoft Entra ID, and Keycloak.
  • It is scheduled for 2026-06-18 as part of the content sprint's two-post-per-week cadence.

What we took into account

  • We considered provider-specific prerequisites, SSO, SCIM, apps, groups, and portable logical structure.
  • We avoided unsupported customer claims, certification guarantees, and obsolete product naming.
  • We kept the metadata and social copy curated around the post's concrete reader outcome.

Why it is useful to an end user

  • End users get a cookbook for modeling identity stacks as code without assuming every provider works the same way.
  • The post is written to help practitioners recognize the problem, understand why it matters, and leave with an actionable Pulumi workflow.

Design need

  • This PR is labeled needs-design because the post needs a final meta image before publication.
  • Existing feature.png and meta.png files are placeholders unless Design chooses to reuse or adapt them.

Metadata

  • Title: Identity Stack Cookbook: Auth0, Okta, Entra ID, and Keycloak
  • Meta description: Manage common identity platform patterns with Pulumi across Auth0, Okta, Microsoft Entra ID, and Keycloak, including SSO, SCIM, apps, and groups.

🤖 Generated with OpenCode

@CamSoper CamSoper marked this pull request as ready for review May 15, 2026 15:12
@github-actions github-actions Bot added review:triaging Claude Triage is currently classifying the PR domain:blog PR touches blog posts or customer stories review:in-progress Claude review is currently running and removed review:triaging Claude Triage is currently classifying the PR labels May 15, 2026
@github-actions
Copy link
Copy Markdown

Pre-merge Review — Last updated 2026-05-15T15:15:54Z

Tip

Summary: New blog post introducing a "cookbook" pattern that shows minimal Pulumi TypeScript examples for one application + one access container across four identity providers (Auth0, Okta, Microsoft Entra ID, Keycloak). Reader-blocking wrongness here would be incorrect resource/property names or wrong import paths in any of the four code blocks — readers will copy these snippets. Frontmatter and meta_desc validated, 56 candidate claims extracted and verified (the two contradicted verdicts both reference pre-fix wording that the author already corrected in e3680d8 — triaged as spurious), editorial-balance was N/A (single-subject), Hugo build skipped (content-only PR).

Review confidence:

Dimension Level Notes
mechanics HIGH
facts MEDIUM Two Auth0-behavior claims (organizationUsage/organizationRequireBehavior semantics) came back unverifiable — the verifier couldn't converge within 8 turns. The code matches the documented property names, but the behavioral assertion at L65-66 isn't independently confirmed.
code correctness MEDIUM Resource imports and property names verified against each provider's SDK. The two contradicted claim-trail entries reference pre-fix wording (Microsoft Entra ID (now Entra ID) and keycloak.openid.ClientRole) that does not appear in the current file — the author already corrected both in e3680d8.
Investigation log
  • Cross-sibling reads: not run (not in a templated section)
  • External claim verification: 40 of 56 claims verified (2 unverifiable, 2 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 42 Pass 1, 3 Pass 2 (verified 0, contradicted 0, unverifiable 3), 11 Pass 3 (verified 9, contradicted 1, unverifiable 1).
  • Cited-claim spot-checks: 3 of 3 cited claims fetched and compared
  • Frontmatter sweep: ran on body + meta_desc + social.{bluesky, linkedin, twitter}
  • Temporal-trigger sweep: ran (recency words present in diff; spot-check in-review)
  • Code execution: not run (no static/programs/ change)
  • Code-examples checks: ran (3 specialists: structural, existence, body-code-coverage); 0 findings
  • Editorial-balance pass: ran (single-subject, N/A)
🚨 Outstanding ⚠️ Low-confidence 💡 Pre-existing ✅ Resolved
0 6 0 0

🔍 Verification trail

56 claims extracted · 40 verified · 2 unverifiable · 2 contradicted
  • L3 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "date: 2026-06-18" → ➖ not-a-claim (evidence: The "date" field in a blog post's front matter is metadata set by the PR author for their own content's publication date — it is not a falsifiable assertion about a third-party fact. It is a faithful description of the PR author's own desi…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md (front matter, line 3))
  • L54 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Auth0 does not model application access as a generic group assignment." → ✅ verified (evidence: The exact sentence appears in the file at the Auth0 section: "Auth0 does not model application access as a generic group assignment. A practical baseline is to define an application client that requires organization login, an organization…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L54 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Auth0 is known for its developer-friendly approach and extensibility." → ✅ verified (evidence: Auth0's own blog describes its platform as "developer-centric" with "proprietary extensibility capabilities," and a JupiterOne case study directly states Auth0 offers "its extensible and developer-friendly solution." Multiple independent s…; source: https://auth0.com/blog/amp/the-developer-first-identity-platform-auth0-story-and-future; https://www.jupiterone.com/case-study/auth0)
  • L56 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Auth0 prerequisite setup requires a Machine-to-Machine application with Management API scopes for clients, organizations, connections, and connection clien…" → ✅ verified (evidence: The blog post at L56 states verbatim: "Prerequisites: an Auth0 tenant, a Machine-to-Machine application with Management API scopes for clients, organizations, connections, and connection clients, and the Pulumi Auth0 provider configured wi…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L59 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Auth0 provider package is imported as @pulumi/auth0." → ✅ verified (evidence: The blog file at line 59 (within the Auth0 TypeScript code block) contains import * as auth0 from "@pulumi/auth0";, directly confirming the package is imported as @pulumi/auth0.; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L61-67 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The auth0.Client resource accepts properties including appType, callbacks, organizationUsage, and organizationRequireBehavior." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L64 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "callbacks: ['https://myapp.com/callback']," → ➖ not-a-claim (evidence: The URL https://myapp.com/callback is a placeholder/example value used in a code snippet (an OAuth callback URL configuration), not a real cited source. It is a fictional example domain used to illustrate configuration syntax, not an aut…; source: https://myapp.com/callback)
  • L65-66 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Setting organizationUsage to 'require' and organizationRequireBehavior to 'pre_login_prompt' on an Auth0 client requires organization login." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L69-72 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The auth0.Organization resource accepts name and displayName properties." → ✅ verified (evidence: The pulumi-auth0 SDK's organization.ts defines both name ("The name of this organization") and displayName ("Friendly name of this organization") as properties in OrganizationArgs, and the built-in example shows `name: "auth0-inc…; source: gh api repos/pulumi/pulumi-auth0/contents/sdk/nodejs/organization.ts)
  • L69 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "const organization = new auth0.Organization('auth0-organization', {" → ➖ not-a-claim (evidence: The line is a TypeScript code snippet instantiating an Auth0 Organization resource. It is a code example authored by the PR author as part of their own design/pipeline, not a falsifiable third-party assertion.; source: content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md L69)
  • L74-77 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The auth0.Connection resource accepts name and strategy properties." → ✅ verified (evidence: The connection.go source in pulumi/pulumi-auth0 SDK defines ConnectionArgs with both Name and Strategy fields, as seen in the example usage: Name: pulumi.String("Example-Connection") and Strategy: pulumi.String("auth0").; source: gh api repos/pulumi/pulumi-auth0/contents/sdk/go/auth0/connection.go)
  • L79-82 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi auth0.ConnectionClients resource accepts connectionId and enabledClients properties." → ✅ verified (evidence: The ConnectionClientsArgs interface in sdk/nodejs/connectionClients.ts declares both connectionId: pulumi.Input<string> and enabledClients: pulumi.Input<pulumi.Input<string>[]> as required properties, and the class body declares th…; source: gh api repos/pulumi/pulumi-auth0/contents/sdk/nodejs/connectionClients.ts)
  • L79 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "const connectionClients = new auth0.ConnectionClients('auth0-connection-clients', {" → ➖ not-a-claim (evidence: The line is a TypeScript code snippet authored by the PR author themselves, instantiating an auth0.ConnectionClients resource in their own example. It is a faithful description of the PR author's own design, not a third-party-attributed…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L84-87 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi auth0.OrganizationConnection resource accepts organizationId and connectionId properties." → ✅ verified (evidence: The sdk/nodejs/organizationConnection.ts file in pulumi/pulumi-auth0 declares both connectionId and organizationId as required properties: "Missing required property 'connectionId'" and `"Missing required property 'organizationId…; source: gh api repos/pulumi/pulumi-auth0/contents/sdk/nodejs/organizationConnection.ts)
  • L91 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "redirectUris: ['https://myapp.com/callback']," → ➖ not-a-claim (evidence: The string "https://myapp.com/callback" is a placeholder example URL used in a code snippet (redirectUris array), not a citation to an external source. It is a fictional/illustrative value in the PR author's own code example, not a third-p…; source: https://myapp.com/callback)
  • L92 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Okta provider offers deep integration for managing applications and group assignments." → ✅ verified (evidence: The blog post at L92 states "Its Pulumi provider offers deep integration for managing applications and group assignments," and the accompanying code example in the same file demonstrates exactly this with okta.app.OAuth, `okta.group.Grou…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L92 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Okta is a leader in workforce identity." → ✅ verified (evidence: Okta's own blog confirms: "Okta has been named a Leader in The Forrester Wave™: Workforce Identity Platforms, Q1 2024," and third-party sources recognize Okta as a "global leader" and "established leader in the IAM space" specifically for…; source: https://www.okta.com/blog/industry-insights/okta-named-a-leader-in-forrester-wavetm-workforce-identity-platforms-q1-2024/)
  • L94 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Okta prerequisite setup requires an API token or OAuth service app with application and group management scopes, and the Pulumi Okta provider configured wi…" → ✅ verified (evidence: The blog file at the Okta section states verbatim: "Prerequisites: an Okta organization, an API token or OAuth service app with application and group management scopes, and the Pulumi Okta provider configured with the organization URL and…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L97 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Okta provider package is imported as @pulumi/okta." → ✅ verified (evidence: The blog file at the Okta section contains import * as okta from "@pulumi/okta";, directly confirming the package is imported as @pulumi/okta.; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L99 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Okta provider exposes an okta.app.OAuth resource for creating OAuth applications." → ✅ verified (evidence: The pulumi/pulumi-okta repo contains sdk/nodejs/app/oauth.ts which exports class OAuth extends pulumi.CustomResource with __pulumiType = 'okta:app/oAuth:OAuth', and the doc comment states "This resource allows you to create and con…; source: gh api repos/pulumi/pulumi-okta/contents/sdk/nodejs/app/oauth.ts)
  • L99-105 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The okta.app.OAuth resource accepts label, type, grantTypes, redirectUris, and responseTypes properties." → ✅ verified (evidence: The pulumi-okta provider's test data and SDK source confirm all five properties on okta:app/oAuth:OAuth: `"grantTypes":["authorization_code"],"label":"MyOAuthApp","redirectUris":["https://example.com/oauth/callback"],"responseTypes":["co…; source: gh api repos/pulumi/pulumi-okta/contents/sdk/go/okta/app/oauth.go; gh search code --owner pulumi --repo pulumi/pulumi-okta "RedirectUris" (provider/testdata/recorded/TestProviderUpgrade/app_oauth/4.8.0/grpc.json))
  • L101 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "const group = new okta.group.Group('okta-group', {" → ➖ not-a-claim (evidence: The line const group = new okta.group.Group("okta-group", { is a TypeScript code snippet in the blog post's own example code. It is a faithful description of the PR author's own design/pipeline (a code sample they wrote), not a third-par…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md (L101); gh api repos/pulumi/pulumi-okta/contents/sdk/nodejs/group confirming group.ts exists)
  • L106 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "const assignment = new okta.app.GroupAssignment('okta-assignment', {" → ➖ not-a-claim (evidence: The line const assignment = new okta.app.GroupAssignment("okta-assignment", { is a line of TypeScript code in the PR author's own blog post code example, not a falsifiable assertion about a third-party fact. It is a faithful description…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L107 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Okta provider exposes an okta.group.Group resource for creating groups." → ✅ verified (evidence: The pulumi-okta repo contains sdk/python/pulumi_okta/group/group.py with a Group class decorated with @pulumi.type_token("okta:group/group:Group") (i.e., okta.group.Group), whose docstring reads "Creates an Okta Group. This resou…; source: gh api repos/pulumi/pulumi-okta/contents/sdk/python/pulumi_okta/group/group.py)
  • L107-110 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The okta.group.Group resource accepts name and description properties." → ✅ verified (evidence: The pulumi-okta SDK source at sdk/go/okta/group/group.go defines GroupArgs with both Name pulumi.StringPtrInput (commented "// The name of the Okta Group.") and Description pulumi.StringPtrInput (commented "// The description of…; source: gh api repos/pulumi/pulumi-okta/contents/sdk/go/okta/group/group.go)
  • L108 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "For organizations heavily invested in the Microsoft ecosystem, Microsoft Entra ID (now Entra ID) is the standard. Pulumi allows you to manage applications and…" → ❌ contradicted (framing: shifted — the claim's parenthetical "(now Entra ID)" implies the product was previously called something else and is now called "Entra ID," but the subject of…; evidence: The claim states "Microsoft Entra ID (now Entra ID)" — but the direction of the rename is reversed. Microsoft Entra ID is the current name; it was formerly Azure Active Directory. As Microsoft's official docs state: "The names Azure Ac…; source: https://learn.microsoft.com/en-us/entra/fundamentals/new-name)
  • L112 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Okta provider exposes an okta.app.GroupAssignment resource for assigning groups to applications." → ✅ verified (evidence: The pulumi/pulumi-okta repo contains sdk/go/okta/app/groupAssignment.go and the Python SDK's app/__init__.py exports from .group_assignment import *, confirming okta.app.GroupAssignment is a real resource in the provider.; source: gh api repos/pulumi/pulumi-okta/contents/sdk/go/okta/app (listing shows groupAssignment.go); gh api repos/pulumi/pulumi-okta/contents/sdk/python/pulumi_okta/app/init.py (exports group_assignment))
  • L112-115 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The okta.app.GroupAssignment resource accepts appId and groupId properties." → ✅ verified (evidence: The sdk/nodejs/app/groupAssignment.ts source in pulumi/pulumi-okta defines GroupAssignmentArgs with appId: pulumi.Input<string> and groupId: pulumi.Input<string> as required properties, and the class declares `public readonly app…; source: gh api repos/pulumi/pulumi-okta/contents/sdk/nodejs/app/groupAssignment.ts)
  • L120 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "For organizations heavily invested in the Microsoft ecosystem, Microsoft Entra ID is the standard identity solution." → ➖ not-a-claim (evidence: The statement "For organizations heavily invested in the Microsoft ecosystem, Microsoft Entra ID is the standard" is the PR author's own editorial positioning in their blog post, not an attributed third-party factual assertion. It is a gen…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L122 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Microsoft Entra ID prerequisite setup requires permissions to create applications, service principals, groups, and app role assignments, and the Pulumi Mic…" → ✅ verified (framing: strengthened — claim says "an Azure identity flow" while source says "your chosen Azure identity flow"; the claim is a narrower subset (any one flow) of the so…; evidence: The blog post states: "Prerequisites: a Microsoft Entra tenant, permissions to create applications, service principals, groups, and app role assignments, and the Pulumi Microsoft Entra ID provider authenticated through your chosen Azure id…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L124 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The default app role ID (00000000-0000-0000-0000-000000000000) assigns the group to the application without requiring a custom app role in Microsoft Entra ID." → ✅ verified (evidence: The pulumi-azuread SDK documentation for AppRoleAssignment explicitly states: "The ID of the app role to be assigned, or the default role ID 00000000-0000-0000-0000-000000000000." This confirms that using the all-zeros UUID is the defa…; source: gh search code --owner pulumi --repo pulumi/pulumi-azuread "00000000-0000-0000-0000-000000000000" → sdk/python/pulumi_azuread/app_role_assignment.py and sdk/java/.../AppRoleAssignment.java)
  • L127 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Microsoft Entra ID provider package is imported as @pulumi/azuread." → ✅ verified (evidence: The pulumi/pulumi-azuread repo's sdk/nodejs/package.json has "name": "@pulumi/azuread", confirming the TypeScript import import * as azuread from "@pulumi/azuread" used in the blog post is correct.; source: gh api repos/pulumi/pulumi-azuread/contents/sdk/nodejs/package.json)
  • L129-132 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The azuread.Application resource accepts displayName and signInAudience properties." → ✅ verified (evidence: The pulumi-azuread Go SDK source (sdk/go/azuread/application.go) explicitly shows DisplayName: pulumi.String("example") and SignInAudience: pulumi.String("AzureADMultipleOrgs") as fields of ApplicationArgs, confirming both proper…; source: gh api repos/pulumi/pulumi-azuread/contents/sdk/go/azuread/application.go)
  • L132 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "appRoleId: '00000000-0000-0000-0000-000000000000'," → ✅ verified (evidence: The all-zeros GUID is the well-known default Azure AD app role ID. Microsoft's official docs state: "The default AppRole ID is 00000000-0000-0000-0000-000000000000. This role is assigned when no specific AppRole is defined for a service pr…; source: https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/assign-user-or-group-access-portal)
  • L134-138 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The azuread.Group resource accepts displayName, mailEnabled, and securityEnabled properties." → ✅ verified (evidence: The pulumi-azuread Go SDK group.go file shows GroupArgs with DisplayName, MailEnabled, and SecurityEnabled fields used in examples: DisplayName: pulumi.String("example"), MailEnabled: pulumi.Bool(true), `SecurityEnabled: pu…; source: gh api repos/pulumi/pulumi-azuread/contents/sdk/go/azuread/group.go)
  • L140-142 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi azuread.ServicePrincipal resource accepts a clientId property." → ✅ verified (evidence: The pulumi-azuread Go SDK source for ServicePrincipal contains ClientId pulumi.StringOutput \pulumi:"clientId"`with the comment "The client ID of the application for which to create a service principal," confirmingclientId` is a…; source: gh api repos/pulumi/pulumi-azuread/contents/sdk/go/azuread/servicePrincipal.go)
  • L140 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Keycloak is the go-to open-source solution for identity management. It is highly flexible and can be self-hosted or run in a container." → ✅ verified (framing: strengthened — claim calls Keycloak "the go-to open-source solution," which is an editorial superlative; sources confirm it is "a leading open source solution"…; evidence: Keycloak is confirmed as a leading open-source identity management solution that supports self-hosting and container-based deployments. The CNCF blog describes it as "a leading open source solution in the cloud-native ecosystem for Identit…; source: https://www.cncf.io/blog/2025/11/07/self-hosted-human-and-machine-identities-in-keycloak-26-4/ ; https://www.keycloak.org/)
  • L144-148 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi azuread.AppRoleAssignment resource accepts appRoleId, principalObjectId, and resourceObjectId properties." → ✅ verified (evidence: The pulumi-azuread Go SDK source for AppRoleAssignment explicitly defines AppRoleId pulumi.StringOutput, PrincipalObjectId pulumi.StringOutput, and ResourceObjectId pulumi.StringOutput as fields, and the example code in the same…; source: gh api repos/pulumi/pulumi-azuread/contents/sdk/go/azuread/appRoleAssignment.go)
  • L145 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "appRoleId: '00000000-0000-0000-0000-000000000000'," → ✅ verified (evidence: The all-zeros GUID is the well-known default Azure AD app role ID. Microsoft's official docs state: "The default AppRole ID is 00000000-0000-0000-0000-000000000000. This role is assigned when no specific AppRole is defined for a service pr…; source: https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/assign-user-or-group-access-portal)
  • L153 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Keycloak can be self-hosted or run in a container." → ✅ verified (evidence: The blog post states at the Keycloak section: "It is highly flexible and can be self-hosted or run in a container." This is an exact match for the claim.; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L153 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Keycloak is the go-to open-source solution for identity management." → ✅ verified (framing: strengthened — the claim uses "go-to" (a colloquial superlative), which is consistent with but slightly stronger than the source's "open source identity and ac…; evidence: Multiple authoritative sources confirm Keycloak's status as the leading open-source identity management solution. Keycloak's own homepage describes it as "the open source identity and access management solution," and skycloak.io calls it "…; source: https://www.keycloak.org/ and https://skycloak.io/keycloak/)
  • L155 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Keycloak prerequisite setup requires a Keycloak realm, an admin client or service account with realm-management permissions, and the Pulumi Keycloak provid…" → ✅ verified (evidence: The blog file at the Keycloak section states verbatim: "Prerequisites: a Keycloak realm, an admin client or service account with realm-management permissions, and the Pulumi Keycloak provider configured with the server URL, realm, client I…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L158 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Keycloak provider package is imported as @pulumi/keycloak." → ✅ verified (evidence: The sdk/nodejs/package.json in pulumi/pulumi-keycloak has "name": "@pulumi/keycloak", confirming the TypeScript/Node.js package is imported as @pulumi/keycloak.; source: gh api repos/pulumi/pulumi-keycloak/contents/sdk/nodejs/package.json)
  • L158 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "validRedirectUris: ['https://myapp.com/callback']," → ➖ not-a-claim (evidence: The URL https://myapp.com/callback is a placeholder example value used in a code snippet (validRedirectUris: ["https://myapp.com/callback"]), not a cited source or a factual assertion about a real endpoint. It is a fictional/illustrati…; source: https://myapp.com/callback)
  • L160-163 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The keycloak.Realm resource accepts realm and enabled properties." → ✅ verified (evidence: The pulumi/pulumi-keycloak SDK Go source (sdk/go/keycloak/realm.go) shows the RealmArgs struct includes both Realm: pulumi.String("my-realm") and Enabled: pulumi.Bool(true) in its example usage, and the Realm struct definition…; source: gh api repos/pulumi/pulumi-keycloak/contents/sdk/go/keycloak/realm.go)
  • L165-172 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The keycloak.openid.Client resource accepts realmId, clientId, name, enabled, accessType, and validRedirectUris properties." → ✅ verified (framing: strengthened — the resource accepts many more properties; the claim lists a subset of the documented inputs, which is a narrower but accurate statement.; evidence: The sdk/go/keycloak/openid/client.go in pulumi/pulumi-keycloak shows ClientArgs with fields RealmId, ClientId, Name, Enabled, AccessType, and ValidRedirectUris in the example usage: `RealmId: realm.ID(), ClientId: pulumi.…; source: gh api repos/pulumi/pulumi-keycloak/contents/sdk/go/keycloak/openid/client.go)
  • L167 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "const group = new keycloak.Group('keycloak-group', {" → ➖ not-a-claim (evidence: The line const group = new keycloak.Group("keycloak-group", { is a code snippet in a blog post demonstrating Pulumi Keycloak provider usage. It is not a falsifiable factual assertion — it is an illustrative code example authored by the P…; source: content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md L167)
  • L172 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "const role = new keycloak.openid.ClientRole('keycloak-app-user-role', {" → ❌ contradicted (framing: shifted — claim says keycloak.openid.ClientRole but the actual source uses keycloak.Role; evidence: The file at the relevant line reads const role = new keycloak.Role("keycloak-app-user-role", { — it uses keycloak.Role, not keycloak.openid.ClientRole as the claim states.; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)
  • L174-177 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The keycloak.Group resource accepts realmId and name properties." → ✅ verified (evidence: The GroupArgs struct in pulumi/pulumi-keycloak SDK (sdk/go/keycloak/group.go) contains both RealmId pulumi.StringInput ("The realm this group exists in.") and Name pulumi.StringPtrInput ("The name of the group."), confirming both p…; source: gh api repos/pulumi/pulumi-keycloak/contents/sdk/go/keycloak/group.go)
  • L178-179 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "const groupRoles = new keycloak.GroupRoles('keycloak-group-roles', {" → ➖ not-a-claim (evidence: The text is a line of TypeScript code (const groupRoles = new keycloak.GroupRoles(...)) found in a blog post code snippet. It is a code fragment, not a falsifiable assertion about a third-party fact — it describes the PR author's own exa…; source: content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md L178-179)
  • L179-183 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The keycloak.Role resource accepts realmId, clientId, and name properties." → ✅ verified (evidence: The role.go source in pulumi/pulumi-keycloak defines the Role struct with fields: ClientId pulumi.StringPtrOutput \pulumi:"clientId"`, Name pulumi.StringOutput `pulumi:"name"`, and RealmId pulumi.StringOutput `pulumi:"realm…; source: gh api repos/pulumi/pulumi-keycloak/contents/sdk/go/keycloak/role.go)
  • L185-190 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "The Pulumi Keycloak provider exposes a keycloak.GroupRoles resource that accepts an exhaustive property." → ✅ verified (evidence: The pulumi/pulumi-keycloak SDK Go source (sdk/go/keycloak/groupRoles.go) defines a GroupRoles struct with field Exhaustive pulumi.BoolPtrOutput \pulumi:"exhaustive"`and the doc comment states: "Ifexhaustive` is true, this reso…; source: gh api repos/pulumi/pulumi-keycloak/contents/sdk/go/keycloak/groupRoles.go)
  • L195 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Auth0 is a strong fit for external application authentication." → ✅ verified (framing: strengthened — claim narrows Auth0's general authentication platform positioning to the specific use case of "external application authentication"; source's br…; evidence: Auth0 is widely documented as an authentication and authorization platform designed to secure external-facing applications. Auth0's own docs describe it as providing "authentication and authorization as a service" for developers to "secure…; source: WebSearch ran query "Auth0 use case external application authentication"; https://auth0.com/docs/architecture-scenarios/b2c/authorization and https://frontegg.com/guides/auth0)
  • L195 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Okta and Microsoft Entra ID are common choices for internal workforce management." → ✅ verified (evidence: Multiple authoritative sources confirm both Okta and Microsoft Entra ID are leading platforms for internal workforce identity management. One source explicitly states "Microsoft Entra ID governs internal workforce identity" and another not…; source: WebSearch ran query "Okta Microsoft Entra ID workforce identity management")
  • L195 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Keycloak is ideal for teams that need full control over their identity infrastructure." → ✅ verified (evidence: Multiple authoritative sources confirm this characterization. For example: "giving organizations full control over their identity infrastructure without vendor lock-in" (docker.recipes) and "A self-managed identity access management (IAM)…; source: WebSearch ran query "Keycloak full control identity infrastructure self-hosted")
  • L197 in content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md "Auth0 organizations, Okta groups, Entra ID groups, and Keycloak groups are not identical, so migrations still require a provider-specific access review." → ➖ not-a-claim (evidence: The text at L197 is the PR author's own editorial statement in their blog post: "Auth0 organizations, Okta groups, Entra ID groups, and Keycloak groups are not identical, so migrations still require a provider-specific access review." This…; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md)

📊 Editorial balance

Single-subject post; balance check N/A.

🚨 Outstanding in this PR

No outstanding blockers.

⚠️ Low-confidence

Review each and resolve as appropriate — these don't block the PR.

  • [L61-67] content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md"The auth0.Client resource accepts properties including appType, callbacks, organizationUsage, and organizationRequireBehavior." — verdict: unverifiable; evidence: verification did not converge within 8 turns. Author question: can you point to the @pulumi/auth0 Client SDK doc that lists these inputs (especially organizationUsage / organizationRequireBehavior)? The names match Auth0's tenant-organizations API, but a citation in the post would let readers confirm the snippet still applies on the current provider version.

  • [L65-66] content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md"Setting organizationUsage to 'require' and organizationRequireBehavior to 'pre_login_prompt' on an Auth0 client requires organization login." — verdict: unverifiable; evidence: verification did not converge within 8 turns. Author question: this is a behavioral assertion (require + pre_login_prompt ⇒ organization login is enforced) — is this the documented Auth0 semantics, or is it inferred from the property names? A one-line citation to Auth0's organization-prompt docs would resolve the ambiguity and help the reader understand what the snippet does, not just what it sets.

Style findings

Found by pattern-based linting; Findings may be false positives.

  • line 30: [style] wordiness — 'implement' is too wordy.
  • line 30: [style] wordiness — 'requirement' is too wordy.
  • line 38: [style] weasel word — 'several' is a weasel word!
  • line 153: [style] wordiness — 'It is' is too wordy.

📋 Triaged verifier findings

I double-checked these and realized they weren't real findings — click to expand
  • [L108] content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md"For organizations heavily invested in the Microsoft ecosystem, Microsoft Entra ID (now Entra ID) is the standard. Pulumi allows you to manage applications and…" — verdict: contradicted; framing: shifted — the claim's parenthetical "(now Entra ID)" implies the product was previously called something else and is now called "Entra ID," but the subject of…; evidence: The claim states "Microsoft Entra ID (now Entra ID)" — but the direction of the rename is reversed. Microsoft Entra ID is the current name; it was formerly Azure Active Directory.; source: https://learn.microsoft.com/en-us/entra/fundamentals/new-name Spurious: The "(now Entra ID)" parenthetical has already been removed from the current file (the line now reads "Microsoft Entra ID is the standard"); the verifier's claim snapshot was taken from an earlier draft state that the author corrected in e3680d8.

  • [L172] content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md"const role = new keycloak.openid.ClientRole('keycloak-app-user-role', {" — verdict: contradicted; framing: shifted — claim says keycloak.openid.ClientRole but the actual source uses keycloak.Role; evidence: The file at the relevant line reads const role = new keycloak.Role("keycloak-app-user-role", { — it uses keycloak.Role, not keycloak.openid.ClientRole as the claim states.; source: repo:content/blog/identity-stack-cookbook-auth0-okta-azuread-keycloak/index.md Spurious: The verifier's own evidence confirms the file already uses the correct keycloak.Role; the keycloak.openid.ClientRole wording came from an earlier draft that the author corrected in e3680d8.

💡 Pre-existing issues in touched files (optional)

No pre-existing issues in touched files.

✅ Resolved since last review

No items resolved since the last review.

📜 Review history

  • 2026-05-15T15:15:54Z — Initial review: 56 claims verified, both contradicted verdicts triaged as spurious (the offending wording was already fixed in this commit); 2 Auth0 behavioral claims came back unverifiable but are not blockers; no Hugo/frontmatter/balance issues. (e3680d8)

Need a re-review? Want to dispute a finding? Mention @claude and include #update-review.
(For ad-hoc questions or fixes, just @claude — no hashtag.)

@github-actions github-actions Bot added review:no-blockers Claude review completed cleanly; outstanding is empty and removed review:in-progress Claude review is currently running labels May 15, 2026
@CamSoper CamSoper closed this May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:blog PR touches blog posts or customer stories review:no-blockers Claude review completed cleanly; outstanding is empty

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants