diff --git a/docs/developer-docs/6.x/navigation.tsx b/docs/developer-docs/6.x/navigation.tsx index 1c3b3f37b..552afa36e 100644 --- a/docs/developer-docs/6.x/navigation.tsx +++ b/docs/developer-docs/6.x/navigation.tsx @@ -161,6 +161,7 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { + diff --git a/docs/developer-docs/6.x/security/cognito-federation.ai.txt b/docs/developer-docs/6.x/security/cognito-federation.ai.txt new file mode 100644 index 000000000..23ed6df41 --- /dev/null +++ b/docs/developer-docs/6.x/security/cognito-federation.ai.txt @@ -0,0 +1,45 @@ +AI Context: Cognito Federation (cognito-federation.mdx) + +Source of Information: +1. packages/cognito/src/Cognito.tsx — defineExtension with federation prop, Pulumi hook, Admin.BuildParam +2. packages/cognito/src/admin/presentation/Cognito/CognitoSignInConfig.ts — ICognitoSignInConfig interface, FederatedProvider union type +3. packages/cognito/src/admin/presentation/Cognito/CognitoPresenter.ts — resolves CognitoSignInConfig, configures Amplify OAuth, populates vm.signIn +4. packages/cognito/src/admin/DefaultCognitoSignInConfig.ts — auto-generated config from BuildParam +5. packages/cognito/src/api/features/CognitoIdp/CognitoIdentityProvider.ts — detects identities claim, sets external: true, merges custom getIdentity +6. packages/cognito/src/api/features/CognitoIdp/abstractions.ts — CognitoIdpConfig interface +7. packages/api-core/src/features/users/ExternalIdpUserSync/ExternalIdpUserSyncHandler.ts — auto-creates/updates external users on AfterLogin +8. packages/cognito/src/infra/CognitoFederationPulumi.ts — CorePulumi hook calling configureAdminCognitoFederation +9. packages/project-aws/src/pulumi/apps/core/cognitoIdentityProviders/configure.ts — configureAdminCognitoFederation, creates domain/IdP/OAuth client +10. packages/cognito/src/admin/presentation/Cognito/components/FederatedLogin.tsx — renders provider buttons, calls signInWithRedirect +11. packages/cognito/src/admin/presentation/Cognito/components/SignIn.tsx — conditionally renders credentials form, FederatedLogin, Divider +12. skills/user-skills/cognito-federation/SKILL.md — full reference skill +13. skills/user-skills/configure-entraid/SKILL.md — Entra ID specific skill + +Key Documentation Decisions: +1. No step-by-step setup guide — AI assistants with Webiny MCP can generate the config from a prompt; the docs focus on concepts and capabilities +2. "Setting It Up with AI" section shows an example prompt for MCP-equipped AI assistants +3. Custom identity mapping only shows overriding roles/teams — defaults for id, displayName, profile are auto-populated from standard Cognito claims +4. adminConfig async example demonstrates IP whitelisting — the most common advanced use case +5. Deploy order section is essential because core must be deployed first to create the Cognito domain, which must then be configured in the external IdP before admin can work + +Understanding: +The federation prop on handles three concerns: +1. Infrastructure (Pulumi) — configureAdminCognitoFederation() creates User Pool Domain, IdentityProvider resources, and configures OAuth on the UserPoolClient +2. Admin login screen — federation config is passed as Admin.BuildParam; DefaultCognitoSignInConfig reads it and implements CognitoSignInConfig.getConfig(); CognitoPresenter resolves it, configures Amplify.configure() with loginWith.oauth, and populates vm.signIn with title/description/allowCredentialsLogin/federatedProviders +3. API identity — CognitoIdentityProvider.getIdentity() builds default identity from token claims, then merges custom CognitoIdpConfig result on top; detects federated users via Boolean(token.identities) and sets external: true; ExternalIdpUserSyncHandler fires on AfterLogin and creates/updates users when external is true + +FederatedProvider is a union: { name, label } renders a default Button; { name, component } renders a custom React component receiving { signIn } callback. + +The adminConfig extension replaces the auto-generated DefaultCognitoSignInConfig with a custom implementation. Because getConfig() is async, runtime checks (IP whitelisting, environment detection) work naturally. + +Related Documents: +- docs/developer-docs/6.x/security/roles.mdx — RoleFactory, roles referenced by slug in identity mapping +- docs/developer-docs/6.x/security/teams.mdx — TeamFactory, teams referenced by slug in identity mapping +- docs/developer-docs/6.x/core-concepts/di.mdx — DI pattern used by CognitoIdpConfig and CognitoSignInConfig + +Key Code Locations: +- packages/cognito/src/Cognito.tsx — extension definition with federation schema +- packages/cognito/src/admin/presentation/Cognito/CognitoSignInConfig.ts — ICognitoSignInConfig, FederatedProvider +- packages/cognito/src/admin/presentation/Cognito/CognitoPresenter.ts — presenter integration +- packages/cognito/src/api/features/CognitoIdp/CognitoIdentityProvider.ts — identity resolution +- packages/cognito/src/api/features/CognitoIdp/abstractions.ts — CognitoIdpConfig diff --git a/docs/developer-docs/6.x/security/cognito-federation.mdx b/docs/developer-docs/6.x/security/cognito-federation.mdx new file mode 100644 index 000000000..bb4883c22 --- /dev/null +++ b/docs/developer-docs/6.x/security/cognito-federation.mdx @@ -0,0 +1,255 @@ +--- +id: a7k2m9x1 +title: Cognito Federation +description: Add federated sign-in (Google, Microsoft Entra ID, OIDC) to the Admin app while keeping Cognito as your user pool. +--- + +import { Alert } from "@/components/Alert"; + + + +- what Cognito Federation is and when to use it +- how to add external identity providers to the login screen +- how federated users are synced into Webiny +- how to customize identity mapping and login screen behavior + + + +## Overview + +By default, Webiny uses a Cognito User Pool where admin users are created manually through the Admin app. Cognito Federation lets you connect external identity providers — Google, Microsoft Entra ID, Facebook, Apple, or any OIDC-compatible provider — so users can sign in with their existing corporate or social credentials. + +Unlike switching to Okta or Auth0 (which replace Cognito entirely), federation keeps Cognito as your user pool. The external provider handles authentication; Cognito issues the tokens; Webiny manages the users. + +### What Happens When a Federated User Signs In + +1. The user clicks a provider button (e.g., "Sign in with Microsoft") on the login screen. +2. Cognito redirects to the external identity provider. +3. After authentication, Cognito creates a session with an `idToken` that includes an `identities` claim. +4. Webiny detects the `identities` claim and marks the user as **external**. +5. On first login, the user is automatically created in Webiny with the roles and teams derived from token claims. +6. On subsequent logins, the user profile is updated if claims have changed. + +External users appear in the Admin app's user management with a read-only badge — they cannot be edited or deleted through the UI since they are managed by the external identity provider. + +## Configuring Federation + +Add a `federation` prop to the `` extension in your `webiny.config.tsx`. This single declaration handles: + +- **AWS infrastructure** — creates the Cognito User Pool Domain, Identity Provider resources, and configures OAuth on the User Pool Client +- **Admin login screen** — shows provider buttons and configures Amplify for the OAuth redirect flow + +```tsx webiny.config.tsx +import { Cognito } from "@webiny/cognito"; + + +``` + +### Federation Config Reference + +| Field | Type | Required | Default | Description | +|-------|------|----------|---------|-------------| +| `domain` | `string` | Yes | — | Cognito User Pool domain prefix | +| `callbackUrls` | `string[]` | Yes | — | OAuth callback URLs (localhost for dev, real domain for prod) | +| `logoutUrls` | `string[]` | No | same as `callbackUrls` | OAuth logout redirect URLs | +| `responseType` | `"code"` or `"token"` | No | `"code"` | OAuth response type | +| `allowCredentialsLogin` | `boolean` | No | `true` | Whether to show the email/password form alongside provider buttons | +| `identityProviders` | array | Yes | — | List of external identity providers | + +### Identity Provider Config + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `type` | `"google"`, `"facebook"`, `"amazon"`, `"apple"`, or `"oidc"` | Yes | Provider type | +| `name` | `string` | For OIDC | Provider name in Cognito (e.g., `"EntraID"`) | +| `label` | `string` | Yes | Button text on the login screen | +| `providerDetails` | `object` | Yes | AWS Cognito provider details — varies by type | +| `attributeMapping` | `object` | No | Override default claim-to-attribute mapping | + + + +For OIDC providers, `providerDetails` must include `client_id`, `client_secret`, and `oidc_issuer`. For social providers (Google, Facebook, etc.), see the [AWS documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-social-idp.html) for the required fields. + + + +## SSO-Only Mode + +To hide the email/password form and show only the federated provider buttons, set `allowCredentialsLogin: false`: + +```tsx + +``` + +The login screen will display a description telling users they'll be redirected to an external service. + +## Custom Identity Mapping + +By default, federated users are created in Webiny with the `full-access` role. To control how token claims map to Webiny roles and teams, provide an `apiConfig` extension: + +```tsx webiny.config.tsx + +``` + +```typescript extensions/cognito/api.ts +import { CognitoIdpConfig } from "@webiny/cognito"; + +class MyConfig implements CognitoIdpConfig.Interface { + getIdentity(token: CognitoIdpConfig.JwtPayload) { + const groups: string[] = (token["cognito:groups"] as string[]) || []; + + return { + roles: groups.includes("admins") ? ["full-access"] : ["content-editor"], + teams: groups.filter(g => g.startsWith("team-")), + }; + } +} + +export default CognitoIdpConfig.createImplementation({ + implementation: MyConfig, + dependencies: [] +}); +``` + + + +You only need to return the fields you want to override. Default values for `id`, `displayName`, and `profile` are automatically derived from standard Cognito token claims (`custom:id`, `given_name`, `family_name`, `email`). + + + +## Custom Login Screen Behavior + +For advanced login screen customization — such as IP-based credential whitelisting or custom provider buttons — provide an `adminConfig` extension that implements `CognitoSignInConfig`: + +```tsx webiny.config.tsx + +``` + +```tsx extensions/cognito/admin.tsx +import { CognitoSignInConfig } from "@webiny/cognito/admin"; + +class MySignInConfig implements CognitoSignInConfig.Interface { + async getConfig() { + return { + oauth: { + scopes: ["profile", "email", "openid"], + redirectSignIn: [window.location.origin], + redirectSignOut: [window.location.origin], + responseType: "code" as const, + }, + allowCredentialsLogin: false, + providers: [ + { name: "EntraID", label: "Sign in with Microsoft" } + ], + title: "Welcome", + description: "Use your corporate credentials to sign in.", + }; + } +} + +export default CognitoSignInConfig.createImplementation({ + implementation: MySignInConfig, + dependencies: [] +}); +``` + +Because `getConfig()` is async, you can perform runtime checks before returning the config: + +```tsx extensions/cognito/admin.tsx +import { CognitoSignInConfig } from "@webiny/cognito/admin"; + +const ALLOWED_IPS = ["1.2.3.4", "5.6.7.8"]; + +class MySignInConfig implements CognitoSignInConfig.Interface { + async getConfig() { + let allowCredentials = false; + if (process.env.REACT_APP_STAGE !== "prod") { + const res = await fetch("https://api64.ipify.org?format=json"); + const { ip } = await res.json(); + allowCredentials = ALLOWED_IPS.includes(ip); + } + + return { + oauth: { + scopes: ["profile", "email", "openid"], + redirectSignIn: [window.location.origin], + redirectSignOut: [window.location.origin], + responseType: "code" as const, + }, + allowCredentialsLogin: allowCredentials, + providers: [ + { name: "EntraID", label: "Sign in with Microsoft" } + ], + }; + } +} + +export default CognitoSignInConfig.createImplementation({ + implementation: MySignInConfig, + dependencies: [] +}); +``` + +## Setting It Up with AI + +If you have the Webiny MCP server connected, you can configure federation with a single prompt: + +> Set up Cognito Federation with Microsoft Entra ID. My tenant ID is `0ae3d912-...`, client ID is `f62ee823-...`, and client secret is `~Hp8Q~...`. Use SSO-only mode — no password login. Map all federated users to the `full-access` role. + +The AI assistant has access to the `webiny-cognito-federation` and `webiny-configure-entraid` skills and will generate the complete configuration. + +## Deploy Order + +1. **Deploy Core** — creates the Cognito User Pool Domain and Identity Provider resources + ```bash + yarn webiny deploy core --env=dev + ``` + +2. **Configure the external IdP** — update the redirect URI in your identity provider's settings to: + `https://{cognitoUserPoolDomain}/oauth2/idpresponse` + (get the domain from `yarn webiny output core --env=dev`) + +3. **Deploy API + Admin** + ```bash + yarn webiny deploy api --env=dev + yarn webiny deploy admin --env=dev + ``` diff --git a/docs/release-notes/6.4.4/changelog.ai.txt b/docs/release-notes/6.4.4/changelog.ai.txt new file mode 100644 index 000000000..6853f5769 --- /dev/null +++ b/docs/release-notes/6.4.4/changelog.ai.txt @@ -0,0 +1,8 @@ +AI Context: 6.4.4 Changelog (changelog.mdx) + +This file tracks manual edits made after the generation script ran. +The script reads the "Skipped PRs" section to avoid re-adding removed entries. + +## Skipped PRs + +## Manual Rewrites diff --git a/docs/release-notes/6.4.4/changelog.mdx b/docs/release-notes/6.4.4/changelog.mdx new file mode 100644 index 000000000..64160cead --- /dev/null +++ b/docs/release-notes/6.4.4/changelog.mdx @@ -0,0 +1,70 @@ +--- +id: k5mqyohu +title: Webiny 6.4.4 Changelog +description: See what's new in Webiny version 6.4.4 +--- + +import { GithubRelease } from "@/components/GithubRelease"; +import { Alert } from "@/components/Alert"; + + + +## Infrastructure + +### Custom Production Environments Are Now Recognized During Deployment ([#5371](https://github.com/webiny/webiny-js/pull/5371)) + +Marking an environment as a production environment via the `Infra.ProductionEnvironments` setting in `webiny.config.tsx` previously had no effect — only the built-in `prod` and `production` names were treated as production, so custom environments (like `stage`) never received production-grade infrastructure such as a VPC. Configured production environments are now correctly recognized and deployed with the appropriate production setup. + + + +If an environment was already deployed before being marked as production, the next deploy will create the VPC, move existing Lambdas into it, add VPC endpoints, and enable resource protection. This is a disruptive infrastructure migration that may replace resources and cause downtime. Review `pulumi preview` carefully and deploy during a maintenance window. + + + +## Development + +### Faster Stack Output Reads via Local Caching ([#5375](https://github.com/webiny/webiny-js/pull/5375)) + +Every stack output lookup previously ran a Pulumi command, which made repeated reads slow—especially during deploys, watch mode, and output lookups that query the same stack multiple times. Stack outputs are now cached locally (under `.webiny/caches/stack-output`) and reused on subsequent reads. The cache is automatically cleared when an app is destroyed, so results always stay accurate. + +## Admin + +### Cognito Federation and Multi-Factor Authentication Support ([#5376](https://github.com/webiny/webiny-js/pull/5376)) + +Webiny now supports federated sign-in through Amazon Cognito, allowing users to authenticate via external identity providers such as Google, Facebook, Apple, Amazon, and any OIDC-compliant provider (e.g., Microsoft Entra ID). This eliminates the need for users to manage separate Webiny credentials when your organization already has an identity provider in place. + +To enable federation, use the `federation` prop on the `` extension: + +```typescript +import { Cognito } from "webiny/api-security-cognito"; + +export default createExtension({ + type: "api", + name: "api.security.cognito", + create() { + return [ + new Cognito({ + federation: { + providers: [ + { + type: "oidc", + name: "EntraID", + label: "Sign in with Microsoft" + } + ] + } + }) + ]; + } +}); +``` + +Federated users are automatically detected via the `identities` claim in the JWT token and flagged as external, triggering the `ExternalIdpUserSyncHandler` for identity mapping and provisioning. + +The login screen can be customized through the `adminConfig` extension point to control which providers appear, whether username/password credentials are shown, and to set custom titles or descriptions. + + + +For new deployments, the `custom:id` attribute maximum length has been increased to 256 characters to accommodate longer OIDC `sub` values from some identity providers. Existing deployments retain the 36-character limit. + + diff --git a/docs/release-notes/6.4.4/upgrade-guide.mdx b/docs/release-notes/6.4.4/upgrade-guide.mdx new file mode 100644 index 000000000..278596270 --- /dev/null +++ b/docs/release-notes/6.4.4/upgrade-guide.mdx @@ -0,0 +1,61 @@ +--- +id: urady4cx +title: Upgrade from 6.4.x to 6.4.4 +description: Learn how to upgrade Webiny from 6.4.x to 6.4.4. +--- + +import { Alert } from "@/components/Alert"; +import { AdditionalNotes } from "@/components/upgrade/AdditionalNotes"; + + + +- how to upgrade Webiny from 6.4.x to 6.4.4 + + + + + +Make sure to check out the [6.4.4 changelog](./changelog) to get familiar with the changes introduced in this release. + + + +## Step-by-Step Guide + +### 1. Upgrade Webiny Packages + +Upgrade all Webiny packages by running the following command: + +```bash +yarn webiny upgrade 6.4.4 --debug +``` + +Note that the command above will run upgrades for all available versions of Webiny up to 6.4.4. If there are upgrades for 6.4.1, 6.4.5, they will be ran. + +You can omit the version to upgrade to the latest available: + +```bash +yarn webiny upgrade --debug +``` + +Once the upgrade has finished, running the `yarn webiny --version` command in your terminal should return **6.4.4**. + + + +If the above command fails or is not available in your setup, you can run the upgrade script directly via `npx`: + +```bash +npx https://github.com/webiny/webiny-upgrades-v6 6.4.4 --debug +``` + + + +### 2. Deploy Your Project + +Proceed by redeploying your Webiny project: + +```bash +# Execute in your project root. +yarn webiny deploy --env {environment} +``` + +