Authlink.Policy.ServiceStack
1.5.0
dotnet add package Authlink.Policy.ServiceStack --version 1.5.0
NuGet\Install-Package Authlink.Policy.ServiceStack -Version 1.5.0
<PackageReference Include="Authlink.Policy.ServiceStack" Version="1.5.0" />
<PackageVersion Include="Authlink.Policy.ServiceStack" Version="1.5.0" />
<PackageReference Include="Authlink.Policy.ServiceStack" />
paket add Authlink.Policy.ServiceStack --version 1.5.0
#r "nuget: Authlink.Policy.ServiceStack, 1.5.0"
#:package Authlink.Policy.ServiceStack@1.5.0
#addin nuget:?package=Authlink.Policy.ServiceStack&version=1.5.0
#tool nuget:?package=Authlink.Policy.ServiceStack&version=1.5.0
Authlink.Policy.ServiceStack
ServiceStack integration for Authlink policy-based authorization. Provides attributes, request filters, and plugins for seamless integration with ServiceStack services.
Installation
dotnet add package Authlink.Policy.ServiceStack
Quick Start
1. Register Services
// Configure.cs or AppHost
public override void Configure(Container container)
{
// Register the policy client (from Authlink.Policy.Client.Http)
container.AddPolicyHttpClient(options =>
{
options.BaseUrl = AppSettings.GetString("PolicyApi:BaseUrl");
});
// Optional: Register resource attribute resolvers
container.AddResourceAttributeResolver(
new TenantResourceResolver(container.Resolve<ITenantService>()));
// Add the plugin
Plugins.Add(new PolicyAuthorizationFeature(options =>
{
options.DefaultResourceKey = "tenant";
options.ThrowOnPolicyError = false;
}));
}
2. Use the PolicyAuthorize Attribute
// Simple permission check
[PolicyAuthorize("reports:view")]
public class GetReports : IReturn<List<Report>> { }
// With resource attributes
[PolicyAuthorize("user:update", ResourceKey = "user", ResourceIdProperty = "Id")]
public class UpdateUser : IReturn<UserResponse>
{
public Guid Id { get; set; }
public string Name { get; set; }
}
// Apply to specific HTTP methods only
[PolicyAuthorize("item:delete", ApplyTo = ApplyTo.Delete)]
public class ManageItem : IReturn<ItemResponse>
{
public Guid Id { get; set; }
}
Features
PolicyAuthorize Attribute
The [PolicyAuthorize] attribute provides declarative policy-based authorization:
| Property | Description |
|---|---|
Permission |
Required. The permission key (e.g., "user:update") |
ResourceKey |
Optional. The resource type for attribute resolution |
ResourceIdProperty |
Optional. Property name on the request DTO containing the resource ID |
ApplyTo |
Optional. HTTP methods to apply (default: All) |
PolicyAuthorizationFeature Plugin
The PolicyAuthorizationFeature is a ServiceStack plugin that registers the authorization filter:
// With default options
Plugins.Add(new PolicyAuthorizationFeature());
// With options configured inline
Plugins.Add(new PolicyAuthorizationFeature(options =>
{
options.DefaultResourceKey = "tenant";
options.UseSessionUserAuthId = true;
}));
// With pre-configured options
var options = new ServiceStackPolicyAuthorizationOptions
{
DefaultResourceKey = "tenant",
ThrowOnPolicyError = true
};
Plugins.Add(new PolicyAuthorizationFeature(options));
Resource Attribute Resolution
Implement IResourceAttributeResolver to provide resource attributes for policy evaluation:
public class TenantResourceResolver : IResourceAttributeResolver
{
private readonly ITenantService _tenantService;
public TenantResourceResolver(ITenantService tenantService)
{
_tenantService = tenantService;
}
public string ResourceKey => "tenant";
public async Task<Dictionary<string, string>> ResolveAsync(
object resourceId,
CancellationToken cancellationToken = default)
{
var tenantId = (Guid)resourceId;
var tenant = await _tenantService.GetByIdAsync(tenantId, cancellationToken);
return new Dictionary<string, string>
{
["tier"] = tenant.Tier.ToString(),
["region"] = tenant.Region ?? "",
["status"] = tenant.Status.ToString()
};
}
}
// Register the resolver
container.AddResourceAttributeResolver(
new TenantResourceResolver(container.Resolve<ITenantService>()));
Configuration Options
Plugins.Add(new PolicyAuthorizationFeature(options =>
{
// Default resource key when not specified on attribute
options.DefaultResourceKey = "tenant";
// Use session's UserAuthId as subject ID (default: true)
options.UseSessionUserAuthId = true;
// Custom claim types to search for subject ID (when not using session)
options.SubjectClaimTypes = new[] { "sub", "user_id" };
// Throw exceptions instead of returning 401/403
options.ThrowOnMissingSubject = false;
options.ThrowOnPolicyError = false;
// Allow missing resource resolvers (logs warning, proceeds without attributes)
options.AllowMissingResourceResolver = false;
}));
Subject ID Extraction
By default, the filter extracts the subject ID from the ServiceStack session's UserAuthId property. The UserAuthId must be a valid GUID string.
Session-Based (Default)
options.UseSessionUserAuthId = true; // Default
The filter will use IAuthSession.UserAuthId from the authenticated session.
Claims-Based
options.UseSessionUserAuthId = false;
options.SubjectClaimTypes = new[] { "sub", "user_id", "nameidentifier" };
When disabled, the filter searches through OAuth access tokens' items for a matching claim.
HTTP Method Filtering
Apply authorization to specific HTTP methods using the ApplyTo property:
// Only authorize DELETE requests
[PolicyAuthorize("item:delete", ApplyTo = ApplyTo.Delete)]
public class ManageItem : IReturn<ItemResponse>
{
public Guid Id { get; set; }
}
// Authorize GET and POST requests
[PolicyAuthorize("report:access", ApplyTo = ApplyTo.Get | ApplyTo.Post)]
public class AccessReport : IReturn<ReportResponse>
{
public Guid ReportId { get; set; }
}
// Multiple attributes for different permissions
[PolicyAuthorize("item:read", ApplyTo = ApplyTo.Get)]
[PolicyAuthorize("item:write", ApplyTo = ApplyTo.Post | ApplyTo.Put)]
public class ItemRequest : IReturn<ItemResponse>
{
public Guid Id { get; set; }
}
Error Handling
The filter responds with appropriate HTTP status codes:
| Scenario | Status Code | Description |
|---|---|---|
| No subject ID | 401 Unauthorized | User not authenticated |
| No resolver found | 403 Forbidden | Resource resolver not registered |
| Resolver error | 403 Forbidden | Failed to resolve resource attributes |
| Policy denied | 403 Forbidden | Access denied by policy |
| Policy error | 500 Internal Server Error | Policy evaluation failed |
Complete Example
// AppHost.cs
public class AppHost : AppHostBase
{
public AppHost() : base("My Api", typeof(MyServices).Assembly) { }
public override void Configure(Container container)
{
// Configure authentication
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] { new JwtAuthProvider(AppSettings) }));
// Register policy client
container.AddPolicyHttpClient(options =>
{
options.BaseUrl = AppSettings.GetString("PolicyApi:BaseUrl");
});
// Register resource resolvers
container.AddResourceAttributeResolver(
new TenantResourceResolver(container.Resolve<ITenantService>()));
container.AddResourceAttributeResolver(
new ProjectResourceResolver(container.Resolve<IProjectService>()));
// Add policy authorization plugin
Plugins.Add(new PolicyAuthorizationFeature(options =>
{
options.DefaultResourceKey = "tenant";
options.UseSessionUserAuthId = true;
}));
}
}
// Services
public class MyServices : Service
{
// Simple permission check
[PolicyAuthorize("tenant:list")]
public async Task<List<TenantDto>> Get(GetTenants request)
{
return await TenantService.GetAllAsync();
}
// With resource attributes
[PolicyAuthorize("tenant:read", ResourceKey = "tenant", ResourceIdProperty = "Id")]
public async Task<TenantDto> Get(GetTenant request)
{
return await TenantService.GetByIdAsync(request.Id);
}
// Different permissions per HTTP method
[PolicyAuthorize("project:read", ApplyTo = ApplyTo.Get)]
[PolicyAuthorize("project:update", ApplyTo = ApplyTo.Put, ResourceKey = "project", ResourceIdProperty = "Id")]
public async Task<ProjectDto> Any(ProjectRequest request)
{
// ...
}
}
Requirements
- .NET 9.0 or later
- ServiceStack 8.x or later
Authlink.Policy.Client.Core(automatically included)IPolicyClientimplementation (e.g.,Authlink.Policy.Client.Http)
Related Packages
Authlink.Policy.Client.Core- Core abstractions and DTOsAuthlink.Policy.Client.Http- HTTP client implementationAuthlink.Policy.AspNetCore- ASP.NET Core integration
License
MIT
| 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
- Authlink.Policy.Client.Core (>= 1.5.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.11)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.11)
- Microsoft.Extensions.Options (>= 10.0.11)
- ServiceStack (>= 8.9.0)
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 |
|---|---|---|
| 1.5.0 | 115 | 9/17/2026 |