diff --git a/Certs/Signing.cs b/Certs/Signing.cs index a6672a2..9185892 100644 --- a/Certs/Signing.cs +++ b/Certs/Signing.cs @@ -1,10 +1,8 @@ using System; -// using System.Security.Cryptography; using Microsoft.IdentityModel.Tokens; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.OpenSsl; -// using BouncyCastle.Crypto; namespace Icarus.Certs; @@ -61,8 +59,6 @@ public class SigningAudienceCertificate : IDisposable using (var reader = System.IO.File.OpenText(file)) { var pem = new PemReader(reader); - // var pem = new Org.BouncyCastle.Utilities.IO.Pem.PemReader(reader); - // var pem = new BouncyCastle.OpenSsl.PemReader(reader); var o = (RsaKeyParameters)pem.ReadObject(); var parameters = new System.Security.Cryptography.RSAParameters(); parameters.Modulus = o.Modulus.ToByteArray(); diff --git a/Constants/DirectoryPaths.cs b/Constants/DirectoryPaths.cs index 1bb39dd..8aab732 100644 --- a/Constants/DirectoryPaths.cs +++ b/Constants/DirectoryPaths.cs @@ -1,6 +1,4 @@ -using System; using System.IO; -using System.Runtime.InteropServices; namespace Icarus.Constants; diff --git a/Constants/FileExtensions.cs b/Constants/FileExtensions.cs index 9b252c5..281526e 100644 --- a/Constants/FileExtensions.cs +++ b/Constants/FileExtensions.cs @@ -10,4 +10,4 @@ public class FileExtensions // Contains file extension with period at the beginning public static string JPG_EXTENSION = ".jpg"; -} \ No newline at end of file +} diff --git a/Controllers/Managers/SongManager.cs b/Controllers/Managers/SongManager.cs index 6797ef8..a17c5f1 100644 --- a/Controllers/Managers/SongManager.cs +++ b/Controllers/Managers/SongManager.cs @@ -241,13 +241,7 @@ public class SongManager : BaseManager } var coverMgr = new CoverArtManager(_config); - var meta = new MetadataRetriever(); var coverArt = coverMgr.SaveCoverArt(coverArtData, song); - // meta.UpdateCoverArt(song, coverArt); - // song.Duration = meta.RetrieveSongDuration(song.SongPath()); - - // meta.UpdateMetadata(song, song); - DirectoryManager dirMgr = new DirectoryManager(_config, song); dirMgr.CreateDirectory(); diff --git a/Controllers/Managers/TokenManager.cs b/Controllers/Managers/TokenManager.cs index 004bb58..ece55fc 100644 --- a/Controllers/Managers/TokenManager.cs +++ b/Controllers/Managers/TokenManager.cs @@ -2,20 +2,13 @@ using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; -using System.Security.Cryptography; using System.Threading.Tasks; using System.IdentityModel.Tokens.Jwt; using System.Text; -using JWT; -using JWT.Serializers; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.OpenSsl; -using Org.BouncyCastle.Security; using RestSharp; using Icarus.Models; @@ -87,37 +80,6 @@ public class TokenManager : BaseManager } - /* - [Obsolete("Asymmetric key signing for tokens have been deprecated")] - public LoginResult LogIn(User user) - { - var tokenResult = new TokenTierOne(); - tokenResult.TokenType = "Jwt"; - - var privateKey = ReadKeyContent(_privateKeyPath).Result; - var publicKey = ReadKeyContent(_publicKeyPath).Result; - - var payload = Payload(); - - var token = CreateToken(payload, privateKey); - tokenResult.AccessToken = token; - - var expClaim = payload.FirstOrDefault(cl => - { - return cl.Type.Equals("exp"); - }); - - tokenResult.Expiration = System.Convert.ToInt32(expClaim.Value); - - return new LoginResult - { - UserID = user.UserID, Username = user.Username, Token = tokenResult.AccessToken, - TokenType = tokenResult.TokenType, Expiration = tokenResult.Expiration, - Message = "Successfully retrieved token" - }; - } - */ - public LoginResult LoginSymmetric(User user) { var tokenResult = new TokenTierOne(); @@ -126,17 +88,6 @@ public class TokenManager : BaseManager var payload = Payload(); payload.Add(new System.Security.Claims.Claim("user_id", user.UserID.ToString(), ClaimValueTypes.Integer)); - /* - var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JWT:Secret"])); - var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - var token = new JwtSecurityToken( - _config["JWT:Issuer"], - _config["JWT:Audience"], - payload, - expires: DateTime.UtcNow.AddMinutes(30), - signingCredentials: signIn); - */ - var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_config["JWT:Secret"]); var tokenDescriptor = new SecurityTokenDescriptor @@ -155,7 +106,6 @@ public class TokenManager : BaseManager var token = tokenHandler.CreateToken(tokenDescriptor); - // tokenResult.AccessToken = new JwtSecurityTokenHandler().WriteToken(token); tokenResult.AccessToken = tokenHandler.WriteToken(token); var expClaim = payload.FirstOrDefault(cl => @@ -175,61 +125,6 @@ public class TokenManager : BaseManager }; } - /* - [Obsolete("Asymmetric key signing for tokens have been deprecated")] - public bool IsTokenValid(string scope, string accessToken) - { - var result = false; - var token = DecodeToken(accessToken); - - if (token == null || token.Erroneous()) - { - return result; - } - - result = (!token.TokenExpired() && token.ContainsScope(scope)) ? true : false; - - // What would make a token valid? - // 1. The expiration date must be before the current date - // 2. The desired scope must be part of the scopes within the access token - // 3. Must be able to be decoded - - return result; - } - - [Obsolete("Asymmetric key signing for tokens have been deprecated")] - public Token DecodeToken(string accessToken) - { - var rsaParams = GetRSAPublic(_publicKey); - Token tok = null; - - try - { - using (var rsa = new RSACryptoServiceProvider()) - { - rsa.ImportParameters(rsaParams); - - IJsonSerializer serializer = new JsonNetSerializer(); - IDateTimeProvider provider = new UtcDateTimeProvider(); - IJwtValidator validator = new JwtValidator(serializer, provider); - IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); - var algorithm = new JWT.Algorithms.RS256Algorithm(rsa); - IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm); - - var json = decoder.Decode(accessToken); - tok = JsonConvert.DeserializeObject(json); - } - } - catch (Exception ex) - { - _logger.Error("An error occurred: {0}", ex.Message); - } - - - return tok; - } - */ - private string AllScopes() { @@ -291,83 +186,6 @@ public class TokenManager : BaseManager return claim; } - /* - [Obsolete("Asymmetric key signing for tokens have been deprecated")] - private string CreateToken(List claims, string privateKey) - { - var token = string.Empty; - - if (string.IsNullOrEmpty(privateKey)) - { - privateKey = ReadKeyContent(_privateKeyPath).Result; - } - - RSAParameters rsaParams; - using (var tr = new System.IO.StringReader(privateKey)) - { - var pemReader = new PemReader(tr); - var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair; - if (keyPair == null) - { - throw new Exception("Could not read RSA private key"); - } - var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters; - rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams); - } - - using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) - { - var rsaParamsPublic = GetRSAPublic(ReadKeyContent(_publicKeyPath).Result); - var rsaPublic = new RSACryptoServiceProvider(); - - rsa.ImportParameters(rsaParams); - rsaPublic.ImportParameters(rsaParamsPublic); - - Dictionary payload = new Dictionary(); - - foreach (var claim in claims) - { - var type = claim.Type; - var val = Int32.TryParse(claim.Value, out _); - - if (val) - { - payload.Add(type, Convert.ToInt32(claim.Value)); - } - else - { - payload.Add(type, claim.Value); - } - - } - - var algorithm = new JWT.Algorithms.RS256Algorithm(rsaPublic, rsa); - IJsonSerializer serializer = new JsonNetSerializer(); - IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); - IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - - token = encoder.Encode(payload, privateKey); - } - - return token; - } - - [Obsolete("Asymmetric key signing for tokens have been deprecated")] - private RSAParameters GetRSAPublic(string publicKey) - { - using (var tr = new System.IO.StringReader(publicKey)) - { - var pemReader = new Org.BouncyCastle.Crypto.PemReader(tr); - var publicKeyParams = pemReader.ReadObject() as RsaKeyParameters; - if (publicKeyParams == null) - { - throw new Exception("Could not read RSA public key"); - } - return DotNetUtilities.ToRSAParameters(publicKeyParams); - } - } - */ - private async Task ReadKeyContent(string filepath) { return await System.IO.File.ReadAllTextAsync(filepath); diff --git a/Controllers/v1/BaseController.cs b/Controllers/v1/BaseController.cs index 11cb5e5..093b470 100644 --- a/Controllers/v1/BaseController.cs +++ b/Controllers/v1/BaseController.cs @@ -4,8 +4,6 @@ using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; -using Icarus.Controllers.Managers; - namespace Icarus.Controllers.V1; @@ -39,16 +37,5 @@ public class BaseController : ControllerBase return token; } - /** - [ApiExplorerSettings(IgnoreApi = true)] - [Obsolete("Asymmetric key signing for tokens have been deprecated")] - protected bool IsTokenValid(string scope) - { - var token = ParseBearerTokenFromHeader(); - var tokMgr = new TokenManager(_config); - - return tokMgr.IsTokenValid(scope, token); - } - */ #endregion } diff --git a/Icarus.csproj b/Icarus.csproj index 0c7d70f..b5fada8 100644 --- a/Icarus.csproj +++ b/Icarus.csproj @@ -1,7 +1,8 @@ - net8 + net8.0 + enable InProcess 0.1.10 diff --git a/Program.cs b/Program.cs index 7820275..fb47ecb 100644 --- a/Program.cs +++ b/Program.cs @@ -1,49 +1,121 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using NLog.Web; +using Icarus.Database.Contexts; -namespace Icarus; -public class Program +var builder = WebApplication.CreateBuilder(args); + +var MAX_REQUEST_BODY_SIZE = 51200000000; + + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(c => { - public static void Main(string[] args) + c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); + + c.SwaggerDoc("v1", new OpenApiInfo { Title = "Icarus", Version = "v1" }); + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() + { + Name = "Authorization", + Scheme = "Bearer", + BearerFormat = "JWT", + Type = SecuritySchemeType.ApiKey, + In = ParameterLocation.Header, + Description = "Bearer *Auth Token*", + }); + c.AddSecurityRequirement(new OpenApiSecurityRequirement { - var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); - - try { - logger.Debug("init main"); - - CreateHostBuilder(args).Build().Run(); - } - catch (Exception ex) - { - logger.Error(ex, "An error occurred"); - throw; - } - finally - { - NLog.LogManager.Shutdown(); - } - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => + new OpenApiSecurityScheme { - webBuilder.UseStartup(); - webBuilder.UseKestrel(options => + Reference = new OpenApiReference { - options.Limits.MaxRequestBodySize = 262144000; - }); - }); + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + new string[] {} + } + }); +}); + +builder.Services.AddControllers(); +builder.WebHost.UseKestrel(option => +{ + option.Limits.MaxRequestBodySize = MAX_REQUEST_BODY_SIZE; +}); + +var Configuration = builder.Configuration; + +var connString = Configuration.GetConnectionString("DefaultConnection"); + +builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => +{ + options.RequireHttpsMetadata = false; + options.SaveToken = true; + options.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuer = true, + ValidateAudience = true, + ValidateIssuerSigningKey = true, + ValidateLifetime = true, + ValidAudience = Configuration["JWT:Audience"], + ValidIssuer = Configuration["JWT:Issuer"], + IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["JWT:Secret"])) + }; +}); + +builder.Services.AddDbContext(options => options.UseMySQL(connString)); +builder.Services.AddDbContext(options => options.UseMySQL(connString)); +builder.Services.AddDbContext(options => options.UseMySQL(connString)); +builder.Services.AddDbContext(options => options.UseMySQL(connString)); +builder.Services.AddDbContext(options => options.UseMySQL(connString)); +builder.Services.AddDbContext(options => options.UseMySQL(connString)); + +builder.Services.AddControllers() + .AddNewtonsoftJson(); + +builder.Services.AddEndpointsApiExplorer(); + + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); } + +// NOTE: This should be enabled at some point +// app.UseHttpsRedirection(); + +app.UseRouting(); +app.UseAuthentication(); +app.UseAuthorization(); +app.UseEndpoints(endpoints => +{ + endpoints.MapControllers(); +}); + +/** +app.MapGet("/weatherforecast", () => +{ + var forecast = Enumerable.Range(1, 5).Select(index => + new WeatherForecast + ( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + summaries[Random.Shared.Next(summaries.Length)] + )) + .ToArray(); + return forecast; +}) +.WithName("GetWeatherForecast") +.WithOpenApi(); +*/ + +app.Run(); diff --git a/Startup.cs b/Startup.cs deleted file mode 100644 index b957940..0000000 --- a/Startup.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Text; -using System.Linq; - -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.EntityFrameworkCore; -using Microsoft.IdentityModel.Tokens; -using Microsoft.OpenApi.Models; -using Newtonsoft.Json; -using NLog; -using NLog.Web; -// using NLog.Web.AspNetCore; - -using Icarus.Database.Contexts; - -namespace Icarus; -public class Startup -{ - #region Constructors - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - #endregion - - #region Properties - public IConfiguration Configuration { get; } - #endregion - - - #region Methods - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddControllers(); - - var auth_id = Configuration["Auth0:Domain"]; - var domain = $"https://{auth_id}/"; - var audience = Configuration["Auth0:ApiIdentifier"]; - - var connString = Configuration.GetConnectionString("DefaultConnection"); - - services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => - { - options.RequireHttpsMetadata = false; - options.SaveToken = true; - options.TokenValidationParameters = new TokenValidationParameters() - { - ValidateIssuer = true, - ValidateAudience = true, - ValidateIssuerSigningKey = true, - ValidateLifetime = true, - ValidAudience = Configuration["JWT:Audience"], - ValidIssuer = Configuration["JWT:Issuer"], - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"])) - }; - }); - - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - - services.AddControllers() - .AddNewtonsoftJson(); - - services.AddEndpointsApiExplorer(); - services.AddSwaggerGen(c => - { - c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); - - c.SwaggerDoc("v1", new OpenApiInfo { Title = "Icarus", Version = "v1" }); - c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() - { - Name = "Authorization", - Scheme = "Bearer", - BearerFormat = "JWT", - Type = SecuritySchemeType.ApiKey, - In = ParameterLocation.Header, - Description = "Bearer *Auth Token*", - }); - c.AddSecurityRequirement(new OpenApiSecurityRequirement - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "Bearer" - } - }, - new string[] {} - } - }); - }); - } - - // Called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - // NOTE: Dev-related configuration can be done when env.IsDevelopment() evaluated to true - if (env.IsDevelopment()) - { - app.UseSwagger(); - app.UseSwaggerUI(); - } - - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - #endregion -}