summaryrefslogtreecommitdiffstats
path: root/src/server/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/Utilities')
-rw-r--r--src/server/Utilities/BasicAuthenticationHandler.cs58
-rw-r--r--src/server/Utilities/SnakeCaseNamingPolicy.cs15
2 files changed, 59 insertions, 14 deletions
diff --git a/src/server/Utilities/BasicAuthenticationHandler.cs b/src/server/Utilities/BasicAuthenticationHandler.cs
index 7961b82..c4124e8 100644
--- a/src/server/Utilities/BasicAuthenticationHandler.cs
+++ b/src/server/Utilities/BasicAuthenticationHandler.cs
@@ -8,10 +8,21 @@ namespace IOL.BookmarkThing.Server.Utilities;
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private readonly AppDbContext _context;
+ private readonly IConfiguration _configuration;
+ private readonly ILogger<BasicAuthenticationHandler> _logger;
- public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, AppDbContext context) :
+ public BasicAuthenticationHandler(
+ IOptionsMonitor<AuthenticationSchemeOptions> options,
+ ILoggerFactory logger,
+ UrlEncoder encoder,
+ ISystemClock clock,
+ AppDbContext context,
+ IConfiguration configuration
+ ) :
base(options, logger, encoder, clock) {
_context = context;
+ _configuration = configuration;
+ _logger = logger.CreateLogger<BasicAuthenticationHandler>();
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync() {
@@ -23,26 +34,45 @@ public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSc
return Task.FromResult(AuthenticateResult.Fail("Missing Authorization Header"));
try {
+ var token_entropy = _configuration.GetValue<string>("TOKEN_ENTROPY");
+ if (token_entropy.IsNullOrWhiteSpace()) {
+ _logger.LogWarning("No token entropy is available in env:TOKEN_ENTROPY, Basic auth is disabled");
+ return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
+ }
+
var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
if (authHeader.Parameter == null) return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
- var token_is_guid = Guid.TryParse(Encoding.UTF8.GetString(credentialBytes), out var token_id);
- if (token_is_guid) {
- var token = _context.AccessTokens.Include(c => c.User).SingleOrDefault(c => c.Id == token_id);
- if (token == default) {
- return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
- }
+ var decrypted_string = Encoding.UTF8.GetString(credentialBytes).DecryptWithAes(token_entropy);
+ var token_is_guid = Guid.TryParse(decrypted_string, out var token_id);
- var claims = token.User.DefaultClaims();
- var identity = new ClaimsIdentity(claims, Scheme.Name);
- var principal = new ClaimsPrincipal(identity);
- var ticket = new AuthenticationTicket(principal, Scheme.Name);
+ if (!token_is_guid) {
+ return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
+ }
- return Task.FromResult(AuthenticateResult.Success(ticket));
+ var token = _context.AccessTokens.Include(c => c.User).SingleOrDefault(c => c.Id == token_id);
+ if (token == default) {
+ return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header: Not Found"));
}
- return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
- } catch {
+ if (token.HasExpired) {
+ return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header: Expired"));
+ }
+
+ var permissions = new List<Claim>() {
+ new(Constants.TOKEN_ALLOW_READ, token.AllowRead.ToString()),
+ new(Constants.TOKEN_ALLOW_UPDATE, token.AllowUpdate.ToString()),
+ new(Constants.TOKEN_ALLOW_CREATE, token.AllowCreate.ToString()),
+ new(Constants.TOKEN_ALLOW_DELETE, token.AllowDelete.ToString()),
+ };
+ var claims = token.User.DefaultClaims().Concat(permissions);
+ var identity = new ClaimsIdentity(claims, Constants.BASIC_AUTH_SCHEME);
+ var principal = new ClaimsPrincipal(identity);
+ var ticket = new AuthenticationTicket(principal, Constants.BASIC_AUTH_SCHEME);
+
+ return Task.FromResult(AuthenticateResult.Success(ticket));
+ } catch (Exception e) {
+ _logger.LogError(e, $"An exception occured when challenging {Constants.BASIC_AUTH_SCHEME}");
return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
}
}
diff --git a/src/server/Utilities/SnakeCaseNamingPolicy.cs b/src/server/Utilities/SnakeCaseNamingPolicy.cs
new file mode 100644
index 0000000..9a7f1f3
--- /dev/null
+++ b/src/server/Utilities/SnakeCaseNamingPolicy.cs
@@ -0,0 +1,15 @@
+namespace IOL.BookmarkThing.Server.Utilities;
+
+public class SnakeCaseNamingPolicy : JsonNamingPolicy
+{
+ public static SnakeCaseNamingPolicy Instance { get; } = new SnakeCaseNamingPolicy();
+
+ public override string ConvertName(string name) {
+ // Conversion to other naming convention goes here. Like SnakeCase, KebabCase etc.
+ return ToSnakeCase(name);
+ }
+
+ private static string ToSnakeCase(string str) {
+ return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())).ToLower();
+ }
+}