Repository navigation
v2.14.0
Three security fixes with one theme: configuration now means what it says. All three are breaking for apps that configure the affected settings; apps that configure nothing are unaffected.
Security
- Configuration can now narrow
IBeam:Identity:AccessControlrole and permission lists, not only widen them.IConfiguration.Bindadds to a collection rather than replacing it, so every list onIBeamAccessControlOptions— which defines who is an owner or an administrator — kept its built-in names no matter what an app configured. An app that setAdminRoleNamesto["RegionalAdmin"]in order to restrict administrator access still treated anyone holding a role namedAdministratororAdminas an administrator, with no warning that its configuration had not taken effect. - OAuth clients configured with explicit
AllowedGrantTypesno longer silently also allowauthorization_code. A client registered for the device-code grant alone previously permitted both. - Tenant invite links are restricted to an allowlist of origins.
DefaultTenantInviteUrlBuilderbuilt the "Accept invitation" link from whateverRedirectUrlthe caller supplied, with no validation, so anyone who could create an invite could send a genuine, app-branded invitation whose button opened a site of their choosing. Separately and independently,DefaultTenantInviteMessageFactorycopied caller-suppliedMetadataover its own values, sometadata: { "inviteUrl": "https://evil.example" }replaced the link even when the redirect URL was valid — and because that dictionary was case-sensitive,InviteUrlreached the template model alongsideinviteUrl. Both paths are closed.
Changed
- Breaking for apps that configure access-control lists. If your app both configures a list under
IBeam:Identity:AccessControland relies on IBeam's built-in values still being present, add those values to your configuration explicitly. The lists:OwnerRoleNames,AdminRoleNames,ApplicationRoleNames,TenantManagementPermissionNames,TenantUserManagementPermissionNames,TenantRoleManagementPermissionNames,TenantAccessControlManagementPermissionNames,ApiCredentialManagementPermissionNames,OAuthClientManagementPermissionNames,AuthAttemptManagementRoleNames,AuthAttemptManagementPermissionNames,AccessLevels. - Breaking for apps that configure OAuth client grant types. A configured
AllowedGrantTypesnow means exactly those grants. An app relying on the implicitauthorization_codealongside its configured grants must list it. - Breaking for apps that send tenant invites. Configure
IBeam:Identity:Invites:Links:DefaultAcceptUrlwith your invite accept page, and list your front-end origins underAllowedOrigins. The previous hardcodedhttps://localhost:3000/invites/acceptfallback is gone — an app that sends an invite without configuring a destination now fails with a message naming the setting. - An OAuth client that specifies no grant types in configuration continues to default to
authorization_code, per RFC 7591 §2. Registering a client programmatically or through the administration API with an explicitly empty grant list is still rejected — configuration cannot express an empty list, but a caller can, and meaning it should not silently earn a grant.
Added — invite link control
Configurable in code as well, which is the point rather than a convenience — AddIBeamTenantInviteLinks's delegate runs after configuration binding, so an app can build the allowlist from its own CORS origins rather than repeating them:
services.AddIBeamTenantInviteLinks(o =>
{
foreach (var origin in myCorsOrigins) o.AllowedOrigins.Add(origin);
// For rules a list cannot express — per-tenant custom domains, preview environments.
// Consulted only after the allowlist says no, and only for a structurally valid URL.
o.IsAllowed = (uri, invite) => uri.Host.EndsWith(".preview.example.com");
});ITenantInviteLinkPolicy is TryAddScoped, so it can be replaced outright. AllowAnyOrigin() restores the pre-2.14.0 behaviour deliberately and logs a warning each time it is used.
Do not populate AllowedOrigins from a CORS wildcard. An app trusting *.example-hosting.net for CORS is trusting every tenant of that host.
Upgrading
- Access control. Search
appsettings*.jsonforIBeam:Identity:AccessControl. If you configure any of the listed lists, that list is now exactly what you wrote — add back any IBeam default you were relying on. - OAuth grants. Search for
AllowedGrantTypes. If a client configures it and also expectsauthorization_code, add it. - Invites. If your app sends tenant invites, configure
DefaultAcceptUrlandAllowedOriginsbefore deploying. This one fails loudly rather than silently, so it will be obvious — but it will be obvious at the moment someone sends an invite. - Apps that configure none of the three need no changes.
The direction of the access-control change matters: before this release, configuration could only ever grant more access than it appeared to. An app unknowingly relying on the old behaviour will find access narrowing on upgrade rather than widening — a failure that is visible, not silent.
Why a minor version
Three breaking changes would ordinarily argue for a major bump. Released as a minor because the blast radius is bounded: each one affects only apps that configure the specific setting involved. Anyone who does should read Upgrading rather than treating this as routine.
Validation
Verified on the released commit (d128420), not on a development branch:
- 676 tests passed across 31 suites, 0 failed, 1 skipped.
- New coverage that binds options from
IConfigurationand asserts the bound values equal exactly what was configured — the gap that let the first two bugs survive:AccessControlOptionsConfigurationTests,OAuthAuthorizationServerOptionsTests,TenantInviteLinkPolicyTests. - The invite tests were checked against the unfixed code: reverting the URL builder fails 1, reverting the metadata merge order fails 2. One test gates the wiring specifically, because the policy tests alone would have passed with a correct policy that nothing used.
Known consumers
- Bindry has already adapted to the access-control change (
BIND-0214), and carries its own app-level invite-link fix (BIND-0124) which it can now delete in favour of registering IBeam's policy with its real CORS origins. It is pinned toIBeamVersion 2.12.2, so bumping crosses2.12.3,2.13.0,2.13.1and this release together. - Every other IBeam consumer should be checked against the Upgrading steps. IBeam is the shared identity layer across seven-plus products, and this release touches who counts as an administrator and where invite emails point.
IBM-0068 · IBM-0072 · IBM-0073