blob: 1c8f9e939ea2417704bae6d1ffd3a9e556519097 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
using ArcaneLibs.Extensions;
using Microsoft.IdentityModel.Tokens;
using Spacebar.AdminAPI.Services;
using Spacebar.Db.Contexts;
using Spacebar.Db.Models;
namespace Spacebar.AdminAPI.Middleware;
public class AuthenticationMiddleware(RequestDelegate next) {
private static Dictionary<string, User> _userCache = new();
private static Dictionary<string, DateTime> _userCacheExpiry = new();
public async Task InvokeAsync(HttpContext context, IServiceProvider sp) {
var config = sp.GetRequiredService<Configuration>();
if (context.Request.Path.StartsWithSegments("/ping") || config.DisableAuthentication) {
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;
}
User user;
if (_userCacheExpiry.ContainsKey(token) && _userCacheExpiry[token] < DateTime.Now) {
_userCache.Remove(token);
_userCacheExpiry.Remove(token);
}
if (!_userCache.ContainsKey(token)) {
var db = sp.GetRequiredService<SpacebarDbContext>();
user = await db.Users.FindAsync(config.OverrideUid ?? res.ClaimsIdentity.Claims.First(x => x.Type == "id").Value)
?? throw new InvalidOperationException();
_userCache[token] = user;
_userCacheExpiry[token] = DateTime.Now.AddMinutes(5);
}
user = _userCache[token];
if (user.Disabled) {
context.Response.StatusCode = 403;
await context.Response.WriteAsync("User is disabled");
return;
}
if (user.Deleted) {
context.Response.StatusCode = 403;
await context.Response.WriteAsync("User is deleted");
return;
}
await next(context);
}
}
|