Rewrite access tokens, initial admin api

This commit is contained in:
Emma [it/its]@Rory& committed 2025-10-05 21:33:50 +02:00
1 parent ccf9afe57e
commit a632666203
65 files changed
+5222 -73

No files matched your search

@@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Spacebar.Db.Contexts;
using Spacebar.Db.Models;
namespace Spacebar.AdminAPI.Controllers;
[ApiController]
[Route("/users")]
public class UserController(ILogger<UserController> logger, SpacebarDbContext db) : ControllerBase {
private readonly ILogger<UserController> _logger = logger;
[HttpGet(Name = "/")]
public IAsyncEnumerable<User> Get() {
return db.Users.AsAsyncEnumerable();
}
}
@@ -0,0 +1,8 @@
using Microsoft.EntityFrameworkCore;
using Spacebar.Db.Models;
namespace Spacebar.AdminAPI.Extensions;
public static class DbExtensions {
public static string? GetString(this DbSet<Config> config, string key) => config.Find(key)?.Value;
}
@@ -0,0 +1,53 @@
using System.Buffers.Text;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
using System.Text;
using ArcaneLibs.Extensions;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.IdentityModel.Tokens;
using Spacebar.AdminAPI.Extensions;
using Spacebar.Db.Contexts;
namespace Spacebar.AdminAPI.Middleware;
public class AuthenticationMiddleware(RequestDelegate next) {
public async Task Invoke(HttpContext context) {
if(Environment.GetEnvironmentVariable("SB_ADMIN_API_DISABLE_AUTH") == "true") {
await next(context);
return;
}
if (!context.Request.Headers.ContainsKey("Authorization")) {
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Authorization header is missing");
return;
}
var token = context.Request.Headers["Authorization"].ToString().Split(' ').Last();
var handler = new JwtSecurityTokenHandler();
var secretFile = File.ReadAllText("../../../jwt.key.pub");
var key = ECDsa.Create(ECCurve.NamedCurves.nistP256);
key.ImportFromPem(secretFile);
var res = await handler.ValidateTokenAsync(token, new TokenValidationParameters {
IssuerSigningKey = new ECDsaSecurityKey(key),
ValidAlgorithms = new[] { "ES512" },
LogValidationExceptions = true,
// These are required to be false for the token to be valid as they aren't provided by the token
ValidateIssuer = false,
ValidateLifetime = false,
ValidateAudience = false,
});
if (!res.IsValid) {
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid token");
return;
}
Console.WriteLine(res.ClaimsIdentity.Claims.Select(x => $"{x.Type} : {x.Value}").ToJson());
await next(context);
}
}
@@ -0,0 +1,58 @@
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.Timeouts;
using Microsoft.EntityFrameworkCore;
using Spacebar.AdminAPI.Middleware;
using Spacebar.Db.Contexts;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers(options => {
options.MaxValidationDepth = null;
options.MaxIAsyncEnumerableBufferLimit = 100;
}).AddJsonOptions(options => {
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
options.JsonSerializerOptions.WriteIndented = true;
});
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddDbContextPool<SpacebarDbContext>(options => {
options
.UseNpgsql(builder.Configuration.GetConnectionString("Spacebar"))
.EnableDetailedErrors();
});
builder.Services.AddRequestTimeouts(x => {
x.DefaultPolicy = new RequestTimeoutPolicy {
Timeout = TimeSpan.FromMinutes(10),
WriteTimeoutResponse = async context => {
context.Response.StatusCode = 504;
context.Response.ContentType = "application/json";
await context.Response.StartAsync();
await context.Response.WriteAsJsonAsync(new { error = "Unknown error" });
await context.Response.CompleteAsync();
}
};
});
builder.Services.AddCors(options => {
options.AddPolicy(
"Open",
policy => policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
var app = builder.Build();
app.UseCors("Open");
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
app.MapOpenApi();
}
app.UseMiddleware<AuthenticationMiddleware>();
app.UseAuthorization();
app.MapControllers();
app.Run();
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"Development": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5112",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Local": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5112",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Local"
}
}
}
}
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ArcaneLibs" Version="1.0.0-preview.20241210-161342" />
<PackageReference Include="ArcaneLibs.StringNormalisation" Version="1.0.0-preview.20241210-161342" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0"/>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Spacebar.Db\Spacebar.Db.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
@Spacebar.AdminAPI_HostAddress = http://localhost:5112
GET {{Spacebar.AdminAPI_HostAddress}}/weatherforecast/
Accept: application/json
###
@@ -0,0 +1,11 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"Spacebar": "Host=127.0.0.1; Username=postgres; Database=spacebar"
}
}
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}