C
C#•3y ago
Welles

.net core webapi2 API key authorization

I was wondering what the absolute best practice was to implement API key authorization for your controllers? - Using middleware (as I'm doing now) - Using Authentication Filters (api key is not really authentication) I'm guessing that if I need only a couple endpoints to be secured I need to use filters, if not I can use middleware? Best regards!
6 Replies
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Welles
WellesOP•3y ago
Well it is custom middleware to check the api key against the database. My app is not public, api is only for local use but still wanted to learn. So at the moment using a middleware that is calling a function in a singleton service I could not find any information online about using api-keys as a header in conjunction with useauthentication/authorization so I got this
public sealed class ApiAuthenticationMiddleware {
private readonly RequestDelegate _next;
private const string _headerName = "x-api-key";

public ApiAuthenticationMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context, [FromServices] AuthenticationService authenticationService)
{
if (!context.Request.Headers.TryGetValue(_headerName, out
var extractedApiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Api Key was not provided ");
return;
}
var valid = authenticationService.IsApiKeyValid(extractedApiKey);
if (!valid)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Unauthorized client");
return;
}
await _next(context);
}
}
public sealed class ApiAuthenticationMiddleware {
private readonly RequestDelegate _next;
private const string _headerName = "x-api-key";

public ApiAuthenticationMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context, [FromServices] AuthenticationService authenticationService)
{
if (!context.Request.Headers.TryGetValue(_headerName, out
var extractedApiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Api Key was not provided ");
return;
}
var valid = authenticationService.IsApiKeyValid(extractedApiKey);
if (!valid)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Unauthorized client");
return;
}
await _next(context);
}
}
public sealed class AuthenticationService
{
private readonly ILogger<AuthenticationService> _logger;
private readonly IDbContextFactory<DataContext> _dbContextFactory;
private List<string> _apiKeys;

public AuthenticationService(ILogger<AuthenticationService> logger,IDbContextFactory<DataContext> dbContextFactory)
{
_dbContextFactory = dbContextFactory;
using var dataContext = _dbContextFactory.CreateDbContext();
_logger = logger;
_apiKeys = dataContext.ApiKey.Select(a => a.key).ToList();
_logger.LogDebug($"{this.GetType().Name} initialized!");
}

public async Task LoadApiKeys()
{
using var dataContext = _dbContextFactory.CreateDbContext();
_apiKeys = await dataContext.ApiKey.Select(a => a.key).ToListAsync();
}

public bool IsApiKeyValid(string apiKey)
{
return _apiKeys.Contains(apiKey);
}
}
public sealed class AuthenticationService
{
private readonly ILogger<AuthenticationService> _logger;
private readonly IDbContextFactory<DataContext> _dbContextFactory;
private List<string> _apiKeys;

public AuthenticationService(ILogger<AuthenticationService> logger,IDbContextFactory<DataContext> dbContextFactory)
{
_dbContextFactory = dbContextFactory;
using var dataContext = _dbContextFactory.CreateDbContext();
_logger = logger;
_apiKeys = dataContext.ApiKey.Select(a => a.key).ToList();
_logger.LogDebug($"{this.GetType().Name} initialized!");
}

public async Task LoadApiKeys()
{
using var dataContext = _dbContextFactory.CreateDbContext();
_apiKeys = await dataContext.ApiKey.Select(a => a.key).ToListAsync();
}

public bool IsApiKeyValid(string apiKey)
{
return _apiKeys.Contains(apiKey);
}
}
All I can find on the internet is telling me to use middleware
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Welles
WellesOP•3y ago
Alright I'll check it to see if I can use it with dbcontext 🙂 thanks!
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Welles
WellesOP•3y ago
I don't really think it is possible to use it for database stuff tbh. the Iapikey expects a public IReadOnlyCollection<Claim> Claims { get; } Not sure how I would get that into the model and database I can work around it with DTO, but then the claims part would be rather useless as it isn't stored. could also serialize the claims stuff myself ofcourse, working with DTO now, works like a charm
Want results from more Discord servers?
Add your server