Shuttle.Access.SqlServer
12.0.1
Prefix Reserved
dotnet add package Shuttle.Access.SqlServer --version 12.0.1
NuGet\Install-Package Shuttle.Access.SqlServer -Version 12.0.1
<PackageReference Include="Shuttle.Access.SqlServer" Version="12.0.1" />
<PackageVersion Include="Shuttle.Access.SqlServer" Version="12.0.1" />
<PackageReference Include="Shuttle.Access.SqlServer" />
paket add Shuttle.Access.SqlServer --version 12.0.1
#r "nuget: Shuttle.Access.SqlServer, 12.0.1"
#:package Shuttle.Access.SqlServer@12.0.1
#addin nuget:?package=Shuttle.Access.SqlServer&version=12.0.1
#tool nuget:?package=Shuttle.Access.SqlServer&version=12.0.1
Shuttle.Access
An Identity and Access Management (IAM) platform providing fine-grained permissions in a session-based, multi-tenant environment. Identities may sign in using an identity name and password, or through a generic OAuth mechanism.
Shuttle.Access consists of a message-processing server, a restful web API, a Vue management front-end, and the NuGet packages that secure your endpoints against it.
Packages
The two client packages have a clean split of responsibility and neither references the other. Pick whichever matches what you are doing; a web API that does both takes both.
| Package | Direction | Purpose |
|---|---|---|
Shuttle.Access.AspNetCore |
inbound | Secures your endpoints against the caller's credential — authentication handler, authorization middleware, and the RequirePermission / RequireSession requirements. |
Shuttle.Access.RestClient |
outbound | Calls the Shuttle.Access web API as your own identity via IAccessClient. Depends on nothing but the contracts, so it works from a console application. |
Shuttle.Access.WebApi.Contracts |
— | Request/response contracts for the web API. |
Shuttle.Access.Messages |
— | Messages published/consumed by the Shuttle.Access server. |
dotnet add package Shuttle.Access.AspNetCore # to secure your endpoints
dotnet add package Shuttle.Access.RestClient # to call Shuttle.Access as yourself
Securing an endpoint
Shuttle.Access.AspNetCore on its own is enough — securing endpoints needs no REST client:
builder.Services
.AddAccessAuthorization(options =>
{
builder.Configuration.GetSection(AccessAuthorizationOptions.SectionName).Bind(options);
options.BaseAddress = "http://localhost:5599"; // the Shuttle.Access web API
});
// ...
app.UseAccessAuthorization();
There is nothing to configure beyond the address of the Shuttle.Access web API. Your application never inspects the
credential it receives — it forwards the caller's Authorization header to GET /v1/sessions/self and takes the
session Shuttle.Access returns. Shuttle.Access is the only place where issuers and tokens are validated, so
security configuration lives in one deployment instead of being duplicated across every application that trusts it.
A caller presents either a Shuttle.Access session token or a JSON Web Token in the Authorization header:
Authorization: Shuttle.Access token={GUID}
Authorization: Bearer {jwt}
An optional Shuttle-Access-Tenant-Id header selects the tenant; when it is absent the configured
AccessOptions.SystemTenantId is used.
Calling Shuttle.Access as yourself
Securing endpoints answers "who is calling me?". A separate question — "who am I, and what may I do?" — is what
Shuttle.Access.RestClient is for. It always calls the web API under your application's own identity, so an
authentication provider is required; without one there would be no credential to send.
builder.Services
.AddAccessClient(options =>
{
options.BaseAddress = "http://localhost:5599";
})
.UsePasswordAuthenticationProvider(providerBuilder =>
{
builder.Configuration.GetSection(PasswordAuthenticationInterceptorOptions.SectionName).Bind(providerBuilder.Options);
});
To discover what your own identity may do, ask for its session — HasPermission is available directly on the
contract:
var response = await accessClient.Sessions.GetSelfAsync(cancellationToken);
if (response is { IsSuccessStatusCode: true, Content: not null } &&
response.Content.HasPermission(tenantId, AccessPermissions.Identities.Register))
{
await accessClient.Identities.PostAsync(registerIdentity, cancellationToken);
}
Every IAccessClient endpoint is available and each is authorized against the permissions assigned to your
identity. Omitting UseBearerAuthenticationProvider() / UsePasswordAuthenticationProvider() fails the host at
startup rather than on the first outbound call.
Console applications
Shuttle.Access.RestClient depends on nothing but the web API contracts and needs no incoming request, so a console
application uses exactly the registration above. AddAccessAuthorization() plays no part — there is no caller to
authorize.
The two are independent
| Securing your endpoints | Calling Shuttle.Access as yourself | |
|---|---|---|
| Package | Shuttle.Access.AspNetCore |
Shuttle.Access.RestClient |
| Credential | the caller's, forwarded as-is | your application's own |
| Endpoint(s) | GET /v1/sessions/self |
the whole IAccessClient |
| Authorized against | the caller's permissions | your application's permissions |
| Entry point | ISessionContext (populated for you) |
IAccessClient |
| Needs an HTTP request | yes | no |
| Needs an authentication provider | no | yes |
Neither package references the other, and a web API that does both simply registers both. Adding an identity of your own never changes how callers are authorized, because the caller's session is always resolved from the forwarded header.
Applying requirements
Minimal API endpoints use RequirePermission or RequireSession:
app.MapGet("/v1/customers", () =>
{
// Requires a specific permission.
})
.RequirePermission("crm://customers/view");
app.MapGet("/v1/customers/{id:guid}", (Guid id) =>
{
// No specific permission, but an active session has to exist.
})
.RequireSession();
MVC controllers use the equivalent attributes:
[HttpGet]
[RequirePermission("crm://customers/view")]
public IEnumerable<Customer> Get()
{
}
[HttpGet("{id:guid}")]
[RequireSession]
public Customer Get(Guid id)
{
}
A request with no session yields 401 Unauthorized; a session without the required permission yields
403 Forbidden.
To check a permission on the caller in code, inject ISessionContext — it is populated during authentication and
carries the resolved session and tenant:
app.MapGet("/v1/categories", (ISessionContext sessionContext) =>
{
if (!sessionContext.HasPermission("pim://categories/review"))
{
return Results.Forbid();
}
return Results.Ok();
});
Permission structure
Permissions are assigned to roles, and roles to identities, per tenant:
.
├─ Permissions
│ ├─ *
│ ├─ system://context/read
│ └─ system://context/write
├─ Roles
│ ├─ Administrator
│ │ └─ Permissions
│ │ └─ *
│ ├─ Reader
│ │ └─ Permissions
│ │ └─ system://context/read
│ └─ Owner
│ └─ Permissions
│ ├─ system://context/read
│ └─ system://context/write
└─ Identity
├─ admin
│ └─ Roles
│ └─ Administrator
├─ someone@domain.com
│ └─ Roles
│ └─ Reader
└─ mrresistor@example.co.za
└─ Roles
└─ Owner
Documentation
Please visit the Shuttle.Access documentation for more information.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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.EntityFrameworkCore.SqlServer (>= 10.0.8)
- Microsoft.Extensions.Configuration.UserSecrets (>= 10.0.8)
- Microsoft.Extensions.Logging.Console (>= 10.0.8)
- Microsoft.Extensions.Logging.Debug (>= 10.0.8)
- Shuttle.Access (>= 12.0.1)
- Shuttle.Recall (>= 21.0.3)
- Shuttle.Recall.SqlServer.EventProcessing (>= 21.0.3)
- Shuttle.Recall.SqlServer.Storage (>= 21.0.3)
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 |
|---|---|---|
| 12.0.1 | 48 | 8/11/2026 |
| 12.0.0 | 52 | 8/11/2026 |
| 11.0.6 | 60 | 8/9/2026 |
| 11.0.5 | 117 | 7/24/2026 |
| 11.0.3 | 115 | 6/25/2026 |
| 11.0.2 | 105 | 6/24/2026 |
| 11.0.1 | 113 | 6/24/2026 |
| 11.0.0 | 108 | 6/24/2026 |
| 10.1.4 | 117 | 6/6/2026 |
| 10.1.3 | 115 | 6/5/2026 |
| 10.1.2 | 102 | 6/5/2026 |
| 10.1.1 | 97 | 6/4/2026 |
| 10.1.0 | 106 | 6/4/2026 |
| 10.0.4 | 117 | 6/1/2026 |
| 10.0.3 | 110 | 6/1/2026 |
| 10.0.2 | 110 | 5/31/2026 |
| 10.0.1 | 121 | 5/23/2026 |
| 10.0.0 | 112 | 5/23/2026 |
| 9.0.8 | 113 | 5/10/2026 |