WIP add API Key authentication
This commit is contained in:
parent
005eea35e2
commit
3f1ab3eb12
5 changed files with 104 additions and 2 deletions
65
src/Robware.Api.Auth/ApiKey/ApiKeyAuthenticationHandler.cs
Normal file
65
src/Robware.Api.Auth/ApiKey/ApiKeyAuthenticationHandler.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Robware.Auth.API;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Robware.Api.Auth.ApiKey {
|
||||
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions> {
|
||||
private const string ApiKeyHeaderName = "X-Api-Key";
|
||||
private readonly IApiKeyValidator _apiKeyValidator;
|
||||
private readonly IApiKeys _apiKeys;
|
||||
|
||||
public ApiKeyAuthenticationHandler(
|
||||
IOptionsMonitor<ApiKeyAuthenticationOptions> options,
|
||||
ILoggerFactory logger,
|
||||
UrlEncoder encoder,
|
||||
ISystemClock clock,
|
||||
IApiKeyValidator apiKeyValidator,
|
||||
IApiKeys apiKeys) : base(options, logger, encoder, clock) {
|
||||
_apiKeyValidator = apiKeyValidator;
|
||||
_apiKeys = apiKeys;
|
||||
}
|
||||
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync() {
|
||||
if (!Request.Headers.TryGetValue(ApiKeyHeaderName, out var apiKeyHeaderValues)) {
|
||||
return AuthenticateResult.NoResult();
|
||||
}
|
||||
|
||||
var providedApiKey = apiKeyHeaderValues.FirstOrDefault();
|
||||
|
||||
if (apiKeyHeaderValues.Count == 0 || string.IsNullOrWhiteSpace(providedApiKey)) {
|
||||
return AuthenticateResult.NoResult();
|
||||
}
|
||||
|
||||
if (await _apiKeyValidator.Validate(providedApiKey)) {
|
||||
var key = await _apiKeys.Get(providedApiKey);
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim(ClaimTypes.Name, key.Name)
|
||||
};
|
||||
|
||||
var identity = new ClaimsIdentity(claims, Options.AuthenticationType);
|
||||
var principal = new ClaimsPrincipal(new[] { identity });
|
||||
var ticket = new AuthenticationTicket(principal, Options.Scheme);
|
||||
|
||||
return AuthenticateResult.Success(ticket);
|
||||
}
|
||||
|
||||
return AuthenticateResult.Fail("Invalid API Key provided.");
|
||||
}
|
||||
|
||||
protected override async Task HandleChallengeAsync(AuthenticationProperties properties) {
|
||||
Response.StatusCode = 401;
|
||||
}
|
||||
|
||||
protected override async Task HandleForbiddenAsync(AuthenticationProperties properties) {
|
||||
Response.StatusCode = 403;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Robware.Api.Auth.ApiKey {
|
||||
public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions {
|
||||
public const string DefaultScheme = "API Key";
|
||||
public string Scheme => DefaultScheme;
|
||||
public string AuthenticationType = DefaultScheme;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using Microsoft.AspNetCore.Authentication;
|
||||
using System;
|
||||
|
||||
namespace Robware.Api.Auth.ApiKey {
|
||||
public static class AuthenticationBuilderExtensions {
|
||||
public static AuthenticationBuilder AddApiKeySupport(this AuthenticationBuilder authenticationBuilder, Action<ApiKeyAuthenticationOptions> options) {
|
||||
return authenticationBuilder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme, options);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using MongoDB.Driver;
|
||||
using Robware.Api.Auth.ApiKey;
|
||||
using Robware.Auth.API;
|
||||
using Robware.Auth.Users;
|
||||
using Robware.Data;
|
||||
|
@ -26,6 +27,12 @@ namespace Robware.Api.Auth {
|
|||
.AddSingleton<IUsers, UserRepository>()
|
||||
.AddSingleton<IApiKeyValidator, ApiKeyValidator>()
|
||||
.AddSingleton<IApiKeys, ApiKeyRepository>();
|
||||
|
||||
services.AddAuthentication(options => {
|
||||
options.DefaultAuthenticateScheme = ApiKeyAuthenticationOptions.DefaultScheme;
|
||||
options.DefaultChallengeScheme = ApiKeyAuthenticationOptions.DefaultScheme;
|
||||
})
|
||||
.AddApiKeySupport(options=>{});
|
||||
}
|
||||
|
||||
private IMongoDatabase SetupMongoDatabase() {
|
||||
|
@ -43,6 +50,8 @@ namespace Robware.Api.Auth {
|
|||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints => {
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
using Robware.Auth.API;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Robware.Data {
|
||||
public class ApiKeyRepository : IApiKeys {
|
||||
public Task<ApiKey> Get(string key) {
|
||||
throw new System.NotImplementedException();
|
||||
public async Task<ApiKey> Get(string key) {
|
||||
if (key=="denied")
|
||||
throw new ApiKeyNotFoundException(key);
|
||||
|
||||
return new ApiKey {
|
||||
Name = "Hardcoded key",
|
||||
Key = key,
|
||||
Enabled = true,
|
||||
IssueTimestamp = DateTime.Now
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue