Tharga.Team.Blazor
3.1.7
dotnet add package Tharga.Team.Blazor --version 3.1.7
NuGet\Install-Package Tharga.Team.Blazor -Version 3.1.7
<PackageReference Include="Tharga.Team.Blazor" Version="3.1.7" />
<PackageVersion Include="Tharga.Team.Blazor" Version="3.1.7" />
<PackageReference Include="Tharga.Team.Blazor" />
paket add Tharga.Team.Blazor --version 3.1.7
#r "nuget: Tharga.Team.Blazor, 3.1.7"
#:package Tharga.Team.Blazor@3.1.7
#addin nuget:?package=Tharga.Team.Blazor&version=3.1.7
#tool nuget:?package=Tharga.Team.Blazor&version=3.1.7
Tharga Team Blazor
Team management Blazor components for multi-tenant applications. Works with both Blazor Server and Blazor WebAssembly.
Components
- Team management -
TeamSelector,TeamComponent,TeamDialog,InviteUserDialog,TeamInviteView. - API key management -
ApiKeyViewfor team-scoped API keys. Row actions are in a single overflow (⋮) context menu (copy, show/hide, audit, edit roles & scopes, lock, refresh, delete). On create or regenerate the key is shown once in a reveal dialog with a copy button and a "shown only once / not stored" warning — required because withAutoLockKeysthe key is locked immediately. Shows Created and Last used columns per key (SystemApiKeyViewshows the same for system keys); the Last used tooltip lists Created / Expiry / Created by (falling back to "System" for keys with no recorded creator, e.g. auto-generated). Also shows a Tags column (system-set key-value tags, displayed read-only via an(i)tooltip). Per-component parameters:ShowScopeTooltip(effective-scope(i), default on),ShowScopeOverrides(scope-override editor),ShowRoles(tenant-role editor),ShowLastUsed(Last used column; 60-day expiry warning),ShowExpiryDatePicker,ShowTags(bool?— null = auto-show when any key has tags),ChipTagKeys,ShowAuditLogButton,AllowGridSorting(sort by Name / Last used, default on, Name ascending),AllowGridFiltering(case-insensitive Name text filter, default off),ShowPrivateKeys(None/Mine/All— include owner-scoped "private" keys; default None) andAllowPrivilegedAccess(let Administrator/Owner see private keys whenAll; view-only).TeamComponentsharesShowScopeTooltip/ShowScopeOverrides/ShowRoles;SystemApiKeyViewuses global system scopes (o.ConfigureSystemScopes). Access is gated on theapikey:managescope; cross-team access comes from mapping a role to system scopes (o.ConfigureSystemRoles), not per-component role parameters. "Last used" writes are throttled byApiKeyOptions.LastUsedThrottle(default 1 min). - Scope explorer -
ScopeViewshows which scopes a member would have: pick an access level (single-select bar; Owner/Administrator are merged since they grant the same scopes) and roles (multi-select bar), and scopes not granted by the selection are greyed out. Defaults to the signed-in member's own access level, roles, and scope overrides (overrides are highlighted with a ⭐ and anOverridebadge). Built dynamically fromIScopeRegistry/ITenantRoleRegistry, so it always reflects the live configuration (no hard-coded list). Parameters:ShowDescription(default on),ShowAccessLevelSelector(default on),ShowRoles(default on; the roles bar auto-hides when no tenant roles are configured),AllowGridSorting(sort by scope name, default on),AllowGridFiltering(case-insensitive name filter, default off). Shows a friendly notice when no scopes are configured. - Custom role management -
TenantRoleManagerlets a team administrator (team:manage) create / edit / delete the team's own runtime-defined custom roles — each granting a chosen subset of the app-registered scopes — without a code deploy. Requireso.EnableDynamicRoles = true. Scopes are picked fromIScopeRegistry(so a role can never grant an unregistered scope), and the server rejects duplicate names or collisions with code-registered roles. Custom roles then appear alongside code roles inTeamComponent's role picker. See "Dynamic (runtime-defined) tenant roles" below. - User management -
UserProfileView,UsersView. - Authentication -
LoginDisplaywith login/logout and team navigation. - Claims augmentation -
TeamClaimsAuthenticationStateProvideraddsTeamKey,AccessLevel, role, and scope claims. Compatible with all hosting models. - Scope enforcement in the circuit -
AddThargaTeamBlazorregisters a circuit-awareITeamPrincipalAccessor, so[RequireScope]/[RequireAccessLevel]on services (registered withAddScopedWithScopes/AddScopedWithAccessLevel) enforce when called from interactive Blazor Server components, not just from controllers/API. - Audit -
AuditLogViewfor viewing audit logs with charts and filtering.
Quick Start (recommended)
Use AddThargaPlatform to register all Platform services in one call:
builder.AddThargaPlatform(o =>
{
o.Blazor.Title = "My App";
o.Blazor.RegisterTeamService<MyTeamService, MyUserService>();
});
var app = builder.Build();
app.UseThargaPlatform();
This registers auth (Azure AD + OIDC), API key authentication, Blazor components, and controllers with sensible defaults. See the main README for the full setup including MongoDB.
Individual Registration
For partial or custom setups, use the individual methods:
Authentication
builder.AddThargaAuth(); // registers auth services
app.UseThargaAuth(); // maps /login and /logout endpoints
Requires an AzureAd section in appsettings.json:
{
"AzureAd": {
"Authority": "https://<tenant>.ciamlogin.com/<domain>",
"ClientId": "<client-id>",
"TenantId": "<tenant-id>",
"CallbackPath": "/signin-oidc"
}
}
Team management
builder.Services.AddThargaTeamBlazor(o =>
{
o.Title = "My App";
o.RegisterTeamService<MyTeamService, MyUserService>();
});
UI components:
<LoginDisplay />— profile menu with Gravatar when authenticated, login button when not.<UserProfileView />— displays the user's profile info and authentication claims.
Per-team role visibility
When TeamComponent's role editor is enabled (ShowRoles), it offers every registered tenant role by default. To hide feature-gated roles from teams where the feature is disabled, register an ITenantRoleVisibilityProvider (from Tharga.Team):
public sealed class FeatureGatedRoleVisibility : ITenantRoleVisibilityProvider
{
public async Task<bool> IsRoleVisibleAsync(string teamKey, string roleName, CancellationToken ct = default)
=> await _features.IsRoleEnabledForTeamAsync(teamKey, roleName, ct);
}
builder.Services.AddSingleton<ITenantRoleVisibilityProvider, FeatureGatedRoleVisibility>();
TeamComponent filters the editor's role list per team through the provider. Hiding a role is UI-only: a role already assigned to a member stays assigned (it is preserved, never pruned, and reappears if the feature is re-enabled) and continues to grant its scopes at runtime. The default provider shows all roles, so this is opt-in and non-breaking.
Dynamic (runtime-defined) tenant roles
Code-registered roles (o.ConfigureTenantRoles) are the same for every team and require a deploy to change. Dynamic tenant roles let a team administrator define their own roles per team at runtime — for example, org-specific operational roles like Registrar / Case officer / Reader / Archivist — each granting a chosen subset of the app-registered scopes.
Enable the feature, then drop the management component on a team:manage-gated page:
builder.AddThargaPlatform(o =>
{
o.ConfigureScopes = s => { s.Register("case:read", AccessLevel.Custom); s.Register("case:write", AccessLevel.Custom); /* … */ };
o.EnableDynamicRoles = true; // registers the team-aware resolver + enables TenantRoleManager
// o.DynamicRoleManageScope = "access:manage"; // optional — scope required to manage custom roles (default team:manage)
});
@attribute [Authorize]
<TenantRoleManager />
- Storage & scope — custom roles live on the team document (per team), created/edited/deleted via
ITeamManagementService.SetTeamCustomRolesAsync, which requiresteam:manageon the team by default. Seto.DynamicRoleManageScope(e.g."access:manage") to gate custom-role CRUD under a dedicated scope instead — enforced by both the service layer andTenantRoleManager. Assigning a role to a member remains amember:manageoperation. - No privilege escalation — a custom role may only grant scopes registered via
o.ConfigureScopes; the server rejects any unregistered scope, duplicate role names, and names that collide with code-registered roles. - Uniform surfacing — when enabled, a member assigned a custom role receives that role's scopes as claims (server, WASM, and API-key paths). Custom roles also appear alongside code roles in the role pickers of
TeamComponent(respectingITenantRoleVisibilityProvider) and, withShowRoles="true",ApiKeyView— so a custom role can be assigned to a team API key. - Off by default — with
EnableDynamicRoles = false(the default) only code roles apply and behaviour is unchanged.
Dependencies
- Tharga.Blazor - Generic UI components.
- Tharga.Team - Domain models and authorization primitives.
- Tharga.Team.Service - Audit types for AuditLogView.
Related packages
| Package | Description |
|---|---|
| Tharga.Team.MongoDB | MongoDB persistence for teams and users |
| Tharga.Team.Service | Server-side API key auth, Swagger, audit logging |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Identity.Web (>= 4.12.0)
- System.Linq.Async (>= 7.0.1)
- Tharga.Blazor (>= 2.2.0)
- Tharga.Team (>= 3.1.7)
- Tharga.Team.Service (>= 3.1.7)
-
net9.0
- Microsoft.Identity.Web (>= 4.12.0)
- System.Linq.Async (>= 7.0.1)
- Tharga.Blazor (>= 2.2.0)
- Tharga.Team (>= 3.1.7)
- Tharga.Team.Service (>= 3.1.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.1.7 | 0 | 7/7/2026 |
| 3.1.6 | 42 | 7/5/2026 |
| 3.1.5 | 46 | 7/5/2026 |
| 3.1.4 | 92 | 7/1/2026 |
| 3.1.3 | 105 | 6/26/2026 |
| 3.1.2 | 107 | 6/23/2026 |
| 3.1.1 | 105 | 6/21/2026 |
| 3.1.0 | 109 | 6/20/2026 |
| 3.0.5 | 99 | 6/20/2026 |
| 3.0.4 | 109 | 6/14/2026 |
| 3.0.3 | 110 | 6/11/2026 |
| 3.0.2 | 113 | 6/4/2026 |
| 3.0.1 | 104 | 6/2/2026 |
| 3.0.0 | 107 | 6/2/2026 |
| 2.1.3 | 102 | 5/30/2026 |
| 2.1.2 | 98 | 5/29/2026 |
| 2.1.1 | 104 | 5/26/2026 |
| 2.1.0 | 100 | 5/18/2026 |
| 2.0.18 | 174 | 5/11/2026 |
| 2.0.17 | 116 | 5/10/2026 |