using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Wabbajack.BuildServer.Model.Models; using Wabbajack.BuildServer.Models; namespace Wabbajack.BuildServer { public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions { public const string DefaultScheme = "API Key"; public string Scheme => DefaultScheme; public string AuthenticationType = DefaultScheme; } public class ApiKeyAuthenticationHandler : AuthenticationHandler { private const string ProblemDetailsContentType = "application/problem+json"; private readonly SqlService _db; private const string ApiKeyHeaderName = "X-Api-Key"; public ApiKeyAuthenticationHandler( IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, SqlService db) : base(options, logger, encoder, clock) { _db = db; } protected override async Task 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(); } var owner = await _db.LoginByAPIKey(providedApiKey); if (owner != null) { var claims = new List {new Claim(ClaimTypes.Name, owner)}; /* claims.AddRange(existingApiKey.Roles.Select(role => new Claim(ClaimTypes.Role, role))); */ var identity = new ClaimsIdentity(claims, Options.AuthenticationType); var identities = new List {identity}; var principal = new ClaimsPrincipal(identities); 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; Response.ContentType = ProblemDetailsContentType; await Response.WriteAsync("Unauthorized"); } protected override async Task HandleForbiddenAsync(AuthenticationProperties properties) { Response.StatusCode = 403; Response.ContentType = ProblemDetailsContentType; await Response.WriteAsync("forbidden"); } } }