home / skills / stuartf303 / sorcha / jwt

jwt skill

/.claude/skills/jwt

This skill helps secure service-to-service and user authorization by implementing JWT Bearer authentication with shared settings and configurable token types.

npx playbooks add skill stuartf303/sorcha --skill jwt

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
3.6 KB
---
name: jwt
description: |
  Implements JWT Bearer authentication for service-to-service and user authorization.
  Use when: Configuring authentication, creating authorization policies, issuing/validating tokens, or troubleshooting 401/403 errors.
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__query-docs
---

# JWT Authentication Skill

Sorcha uses **JWT Bearer authentication** with the **Tenant Service** as the token issuer. All services validate tokens using shared `JwtSettings` from `Sorcha.ServiceDefaults`. Tokens support three types: user (email/password), service (client credentials), and delegated (service acting on behalf of user).

## Quick Start

### Service Authentication Setup

```csharp
// Program.cs - Any Sorcha service
var builder = WebApplication.CreateBuilder(args);

// 1. Add JWT authentication (shared key auto-generated in dev)
builder.AddJwtAuthentication();

// 2. Add service-specific authorization policies
builder.Services.AddBlueprintAuthorization();

var app = builder.Build();

// 3. CRITICAL: Order matters!
app.UseAuthentication();
app.UseAuthorization();

app.MapBlueprintEndpoints();
app.Run();
```

### Protect an Endpoint

```csharp
// Minimal API pattern
group.MapPost("/", CreateBlueprint)
    .WithName("CreateBlueprint")
    .RequireAuthorization("CanManageBlueprints");
```

## Key Concepts

| Concept | Usage | Example |
|---------|-------|---------|
| Token Types | Differentiate user vs service | `token_type` claim: `"user"` or `"service"` |
| Organization Scope | Isolate tenant data | `org_id` claim in token |
| Signing Key | Symmetric HMAC-SHA256 | Auto-generated in dev, Azure Key Vault in prod |
| Token Lifetime | Configurable per type | Access: 60min, Refresh: 24hr, Service: 8hr |

## Common Patterns

### Custom Authorization Policy

**When:** Endpoint requires specific claims beyond role-based auth.

```csharp
// AuthenticationExtensions.cs
options.AddPolicy("CanManageBlueprints", policy =>
    policy.RequireAssertion(context =>
    {
        var hasOrgId = context.User.Claims.Any(c => c.Type == "org_id" && !string.IsNullOrEmpty(c.Value));
        var isService = context.User.Claims.Any(c => c.Type == "token_type" && c.Value == "service");
        return hasOrgId || isService;
    }));
```

### Extract Claims in Handler

**When:** Need user/org context in endpoint logic.

```csharp
async Task<IResult> HandleRequest(ClaimsPrincipal user, ...)
{
    var userId = user.FindFirst(JwtRegisteredClaimNames.Sub)?.Value;
    var orgId = user.FindFirst("org_id")?.Value;
    
    if (string.IsNullOrEmpty(orgId))
        return Results.Forbid();
    
    // Use orgId for data isolation
}
```

## See Also

- [patterns](references/patterns.md) - Token generation, validation, policies
- [workflows](references/workflows.md) - Setup, testing, troubleshooting

## Related Skills

- See the **minimal-apis** skill for endpoint configuration with `.RequireAuthorization()`
- See the **aspire** skill for shared configuration via `ServiceDefaults`
- See the **redis** skill for token revocation tracking
- See the **yarp** skill for gateway-level authentication

## Documentation Resources

> Fetch latest JWT/authentication documentation with Context7.

**How to use Context7:**
1. Use `mcp__context7__resolve-library-id` to search for "asp.net core authentication jwt"
2. **Prefer website documentation** (IDs starting with `/websites/`) over source code repositories
3. Query with `mcp__context7__query-docs` using the resolved library ID

**Recommended Queries:**
- "JWT Bearer authentication setup"
- "authorization policies claims"
- "token validation parameters"

Overview

This skill implements JWT Bearer authentication for service-to-service and user authorization using the Tenant Service as the issuer. It centralizes token validation and shared JwtSettings so all services use a consistent signing key, claims model, and lifetimes. The skill supports user, service, and delegated token types and provides helpers to register authentication and authorization policies in a Sorcha service.

How this skill works

Add the provided AddJwtAuthentication extension to wire up JWT Bearer with the shared JwtSettings. Services call AddBlueprintAuthorization to register common policies. Middleware ordering is critical: the app must call UseAuthentication() before UseAuthorization(). Tokens contain claims like token_type and org_id and are validated with a symmetric signing key (dev auto-generated, production via Key Vault).

When to use it

  • Configuring authentication for a new Sorcha service or API.
  • Creating authorization policies that require tenant or token-type checks.
  • Issuing or validating access, refresh, service, or delegated tokens.
  • Troubleshooting 401/403 responses caused by missing/invalid claims.
  • Implementing service-to-service client credentials flows or delegated calls.

Best practices

  • Always call app.UseAuthentication() before app.UseAuthorization(); middleware order matters.
  • Keep org_id and token_type as part of tokens to enforce tenant isolation and token intent.
  • Use Key Vault or another secure store for the signing key in production; only rely on auto-generated keys in dev.
  • Define focused authorization policies (RequireAssertion) that check specific claims rather than broad role checks.
  • Validate token lifetimes appropriate to the token type (shorter lifetimes for access tokens, longer for refresh).

Example use cases

  • Protect a Minimal API endpoint with .RequireAuthorization("CanManageBlueprints") to restrict create operations.
  • Issue a service token for background jobs that call other services (token_type: service).
  • Handle delegated calls where a service acts on behalf of a user and requires both user and service context.
  • Extract sub and org_id claims in handlers to enforce data isolation and return Forbid when org_id is missing.
  • Troubleshoot 401s by inspecting token_type, org_id, and token expiration in incoming JWTs.

FAQ

What token types are supported and how are they distinguished?

The skill supports user, service, and delegated tokens, distinguished by the token_type claim (e.g., "user" or "service").

How should I store the signing key in production?

Store the HMAC signing key in a secure secret store such as Azure Key Vault and load it into JwtSettings; do not use dev auto-generated keys in production.