Back to list
medride

dotnet-api-auth

by medride

0🍴 0📅 Jan 21, 2026

SKILL.md


name: dotnet-api-auth description: Authentication and authorization patterns for ASP.NET Core Web APIs

.NET API Authentication Skill

Patterns and implementations for securing ASP.NET Core Web APIs with authentication and authorization.

JWT Bearer Authentication

Configure JWT Bearer authentication in Program.cs:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
        };
    });

// Add after building the app
app.UseAuthentication();
app.UseAuthorization();

Required appsettings.json configuration:

{
  "Jwt": {
    "Key": "your-256-bit-secret-key-here-min-32-chars",
    "Issuer": "https://yourdomain.com",
    "Audience": "https://yourdomain.com"
  }
}

API Key Authentication

Custom middleware for API key validation:

public class ApiKeyMiddleware
{
    private const string ApiKeyHeaderName = "X-API-Key";
    private readonly RequestDelegate _next;

    public ApiKeyMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context, IConfiguration config)
    {
        if (!context.Request.Headers.TryGetValue(ApiKeyHeaderName, out var extractedApiKey))
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsync("API Key is missing");
            return;
        }

        var apiKey = config["ApiKey"];
        if (!apiKey.Equals(extractedApiKey))
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsync("Invalid API Key");
            return;
        }

        await _next(context);
    }
}

// Register in Program.cs
app.UseMiddleware<ApiKeyMiddleware>();

Policy-Based Authorization

Define and register authorization policies:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"))
    .AddPolicy("PremiumUser", policy => policy.RequireClaim("Subscription", "Premium"))
    .AddPolicy("MinimumAge", policy =>
        policy.Requirements.Add(new MinimumAgeRequirement(18)));

// Register custom handlers
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();

Apply policies to endpoints:

[Authorize(Policy = "AdminOnly")]
[HttpDelete("{id}")]
public IActionResult Delete(int id) { /* ... */ }

// Or with minimal APIs
app.MapDelete("/admin/users/{id}", () => Results.Ok())
    .RequireAuthorization("AdminOnly");

Claims and Roles

Access claims in controllers:

[Authorize]
[HttpGet("profile")]
public IActionResult GetProfile()
{
    var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    var email = User.FindFirst(ClaimTypes.Email)?.Value;
    var roles = User.FindAll(ClaimTypes.Role).Select(c => c.Value);

    return Ok(new { userId, email, roles });
}

// Check roles
if (User.IsInRole("Admin"))
{
    // Admin-specific logic
}

Generate tokens with claims:

public string GenerateToken(User user)
{
    var claims = new List<Claim>
    {
        new(ClaimTypes.NameIdentifier, user.Id.ToString()),
        new(ClaimTypes.Email, user.Email),
        new(ClaimTypes.Role, user.Role),
        new("CustomClaim", "CustomValue")
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
    var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(
        issuer: _config["Jwt:Issuer"],
        audience: _config["Jwt:Audience"],
        claims: claims,
        expires: DateTime.UtcNow.AddHours(1),
        signingCredentials: credentials);

    return new JwtSecurityTokenHandler().WriteToken(token);
}

Resource-Based Authorization

Authorize access to specific resources:

public class DocumentAuthorizationHandler :
    AuthorizationHandler<OperationAuthorizationRequirement, Document>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        OperationAuthorizationRequirement requirement,
        Document resource)
    {
        var userId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;

        if (requirement.Name == Operations.Read.Name && resource.OwnerId == userId)
        {
            context.Succeed(requirement);
        }

        if (requirement.Name == Operations.Update.Name &&
            (resource.OwnerId == userId || context.User.IsInRole("Admin")))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

Use in a controller:

public class DocumentsController : ControllerBase
{
    private readonly IAuthorizationService _authService;

    [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id)
    {
        var document = await _repository.GetAsync(id);
        var result = await _authService.AuthorizeAsync(User, document, Operations.Read);

        if (!result.Succeeded)
            return Forbid();

        return Ok(document);
    }
}

CORS Configuration

Configure CORS for API access:

builder.Services.AddCors(options =>
{
    // Named policy for specific origins
    options.AddPolicy("AllowSpecificOrigin", policy =>
    {
        policy.WithOrigins("https://example.com", "https://app.example.com")
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials();
    });

    // Development policy (more permissive)
    options.AddPolicy("Development", policy =>
    {
        policy.AllowAnyOrigin()
              .AllowAnyMethod()
              .AllowAnyHeader();
    });
});

// Apply globally
app.UseCors("AllowSpecificOrigin");

// Or per-endpoint
app.MapGet("/api/public", () => "Hello")
    .RequireCors("AllowSpecificOrigin");

Quick Reference

PatternUse CaseKey Components
JWT BearerToken-based authAddJwtBearer, TokenValidationParameters
API KeySimple service authCustom middleware, header validation
Policy-BasedRole/claim requirementsAddPolicy, [Authorize(Policy)]
Resource-BasedPer-resource permissionsIAuthorizationService, custom handlers
CORSCross-origin requestsAddCors, UseCors

Additional Resources

  • See examples/jwt-setup-example.cs for complete JWT configuration
  • See examples/policy-auth-example.cs for custom authorization requirements

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon