Branca.AspNetCore 0.8.1

dotnet add package Branca.AspNetCore --version 0.8.1
                    
NuGet\Install-Package Branca.AspNetCore -Version 0.8.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Branca.AspNetCore" Version="0.8.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Branca.AspNetCore" Version="0.8.1" />
                    
Directory.Packages.props
<PackageReference Include="Branca.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Branca.AspNetCore --version 0.8.1
                    
#r "nuget: Branca.AspNetCore, 0.8.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Branca.AspNetCore@0.8.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Branca.AspNetCore&version=0.8.1
                    
Install as a Cake Addin
#tool nuget:?package=Branca.AspNetCore&version=0.8.1
                    
Install as a Cake Tool

Branca.AspNetCore

ASP.NET Core authentication for Branca tokens, letting you protect endpoints with [Authorize] using encrypted Branca tokens instead of JWTs.

Branca tokens are symmetric: the service that validates a token can also issue one. That makes this a good fit for first-party session and API tokens, where the same application (or a trusted set sharing the secret key) both issues and validates. For federated scenarios that need third parties to validate without the secret, an asymmetric JWT remains the better tool.

Usage

Register the scheme with a 32-byte key:

using Branca;

builder.Services
  .AddAuthentication(BrancaDefaults.AuthenticationScheme)
  .AddBranca(options =>
  {
    options.Key = BrancaKey.FromBase64Url(builder.Configuration["Branca:Key"]!);
    options.TokenLifetimeInSeconds = 3600;
  });

builder.Services.AddAuthorization();
app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/me", (ClaimsPrincipal user) => user.Identity!.Name)
  .RequireAuthorization();

Clients send the token in the Authorization header:

Authorization: Bearer <branca-token>

Issuing Tokens

Register the key once on the service collection instead, and both the scheme and your issuing endpoints share one IBrancaService:

builder.Services.AddBranca(
  BrancaKey.FromBase64Url(builder.Configuration["Branca:Key"]!));

builder.Services
  .AddAuthentication(BrancaDefaults.AuthenticationScheme)
  .AddBranca();
app.MapPost("/login", (IBrancaService branca) =>
  branca.Encode("""{ "name": "alice", "role": ["admin"] }"""));

Key rotation and clock skew come from the registered BrancaSettings, or from BrancaOptions when the scheme is configured with an explicit key:

builder.Services.AddBranca(currentKey, new BrancaSettings
{
  PreviousKeys = [previousKey],
  ClockSkewInSeconds = 300,
});

The package is trimming and Native AOT compatible.

Claims

By default the decrypted payload is read as a flat JSON object, and each property becomes a claim. Array values (such as "role": ["admin", "user"]) yield one claim per element, so [Authorize(Roles = "admin")] works out of the box. The name and role claim types are configurable via NameClaimType and RoleClaimType, and the whole mapping can be replaced through MapClaims for non-JSON payloads such as MessagePack.

MessagePack payloads are typically int-keyed, so a typed mapping through your own payload contract works better than any generic convention:

options.MapClaims = payload =>
{
  TokenPayload data = MessagePackSerializer.Deserialize<TokenPayload>(payload);

  return
  [
    new Claim("sub", data.Subject.ToString()),
    new Claim("name", data.Name),
  ];
};

Returning null rejects the token, and an exception thrown by the mapping fails authentication rather than the request.

Token expiry is enforced by the token format itself through TokenLifetimeInSeconds; there is no separate exp claim to validate.

See the repository for more.

License

Free software, licensed under the GNU Lesser General Public License v3.0 or later.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
0.8.1 114 7/11/2026
0.8.0 106 7/11/2026