From 25d8f9b40dcdf375b2a7a8ecbceca9217a0f8c85 Mon Sep 17 00:00:00 2001 From: "Jamie.Rees" Date: Fri, 22 Sep 2017 16:28:12 +0100 Subject: [PATCH] !minor removed the encryption for now while I investigate #865 --- src/Ombi.DependencyInjection/IocExtensions.cs | 10 +- src/Ombi.Settings/Settings/SettingsService.cs | 8 +- src/Ombi/Startup.cs | 111 ++++-------------- src/Ombi/StartupExtensions.cs | 96 +++++++++++++++ 4 files changed, 130 insertions(+), 95 deletions(-) create mode 100644 src/Ombi/StartupExtensions.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index ee7e4c444..e4f434087 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -1,7 +1,9 @@ using System.Diagnostics.CodeAnalysis; +using System.Security.Principal; using Hangfire; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; @@ -49,13 +51,14 @@ namespace Ombi.DependencyInjection [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class IocExtensions { - public static void RegisterDependencies(this IServiceCollection services) + public static void RegisterApplicationDependencies(this IServiceCollection services) { services.RegisterEngines(); services.RegisterApi(); services.RegisterServices(); services.RegisterStore(); services.RegisterJobs(); + services.RegisterHttp(); } public static void RegisterEngines(this IServiceCollection services) @@ -68,6 +71,11 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); } + public static void RegisterHttp(this IServiceCollection services) + { + services.AddSingleton(); + services.AddScoped(sp => sp.GetService().HttpContext.User); + } public static void RegisterApi(this IServiceCollection services) { diff --git a/src/Ombi.Settings/Settings/SettingsService.cs b/src/Ombi.Settings/Settings/SettingsService.cs index 5bcf1a835..305c3f3a7 100644 --- a/src/Ombi.Settings/Settings/SettingsService.cs +++ b/src/Ombi.Settings/Settings/SettingsService.cs @@ -9,7 +9,7 @@ using Microsoft.AspNetCore.DataProtection; namespace Ombi.Settings.Settings { public class SettingsService : ISettingsService - where T : Ombi.Settings.Settings.Models.Settings, new() + where T : Models.Settings, new() { public SettingsService(ISettingsRepository repo, IDataProtectionProvider provider) @@ -127,12 +127,14 @@ namespace Ombi.Settings.Settings private string EncryptSettings(GlobalSettings settings) { - return _protector.Protect(settings.Content); + return settings.Content; + //return _protector.Protect(settings.Content); } private string DecryptSettings(GlobalSettings settings) { - return _protector.Unprotect(settings.Content); + return settings.Content; + //return _protector.Unprotect(settings.Content); } } } \ No newline at end of file diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 34d55cf5f..6b553abc7 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -59,11 +59,11 @@ namespace Ombi //if (env.IsDevelopment()) //{ - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "Logs", "log-{Date}.txt")) - .WriteTo.SQLite("Ombi.db", "Logs", LogEventLevel.Debug) - .CreateLogger(); + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "Logs", "log-{Date}.txt")) + .WriteTo.SQLite("Ombi.db", "Logs", LogEventLevel.Debug) + .CreateLogger(); //} //if (env.IsProduction()) //{ @@ -82,7 +82,7 @@ namespace Ombi { // Add framework services. services.AddDbContext(); - + services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); @@ -96,88 +96,23 @@ namespace Ombi options.Password.RequireUppercase = false; }); + services.AddDataProtection(); services.AddMemoryCache(); - var tokenOptions = Configuration.GetSection("TokenAuthentication"); - - var tokenValidationParameters = new TokenValidationParameters - { - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.GetValue("SecretKey", string.Empty))), - - RequireExpirationTime = true, - ValidateLifetime = true, - ValidAudience = "Ombi", - ValidIssuer = "Ombi", - ClockSkew = TimeSpan.Zero, - }; - - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(x => - { - x.Audience = "Ombi"; - x.TokenValidationParameters = tokenValidationParameters; - }); + services.AddJwtAuthentication(Configuration); services.AddMvc() .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); - + services.AddOmbiMappingProfile(); services.AddAutoMapper(expression => { expression.AddCollectionMappers(); }); - services.RegisterDependencies(); // Ioc and EF - services.AddSwaggerGen(c => - { - c.DescribeAllEnumsAsStrings(); - c.SwaggerDoc("v1", new Info - { - Version = "v1", - Title = "Ombi Api", - Description = "The API for Ombi, most of these calls require an auth token that you can get from calling POST:\"/connect/token/\" with the body of: \n {\n\"username\":\"YOURUSERNAME\",\n\"password\":\"YOURPASSWORD\"\n} \n" + - "You can then use the returned token in the JWT Token field e.g. \"Bearer Token123xxff\"", - Contact = new Contact - { - Email = "tidusjar@gmail.com", - Name = "Jamie Rees", - Url = "https://www.ombi.io/" - } - }); - c.CustomSchemaIds(x => x.FullName); - var basePath = PlatformServices.Default.Application.ApplicationBasePath; - var xmlPath = Path.Combine(basePath, "Swagger.xml"); - try - { - c.IncludeXmlComments(xmlPath); - } - catch (Exception e) - { - Console.WriteLine(e); - } - c.AddSecurityDefinition("Bearer", new ApiKeyScheme() - { - Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", - Name = "Authorization", - In = "header", - Type = "apiKey" - }); - c.AddSecurityDefinition("Authentication", new ApiKeyScheme()); - c.OperationFilter(); - c.DescribeAllParametersInCamelCase(); - }); - - services.AddSingleton(); - services.AddScoped(sp => sp.GetService().HttpContext.User); - - services.Configure(Configuration.GetSection("ApplicationSettings")); - services.Configure(Configuration.GetSection("UserSettings")); - services.Configure(Configuration.GetSection("TokenAuthentication")); - services.Configure(Configuration.GetSection("LandingPageBackground")); + services.RegisterApplicationDependencies(); // Ioc and EF + services.AddSwagger(); + services.AddAppSettingsValues(Configuration); services.AddHangfire(x => { @@ -188,10 +123,7 @@ namespace Ombi }); // Build the intermediate service provider - var serviceProvider = services.BuildServiceProvider(); - - //return the provider - return serviceProvider; + return services.BuildServiceProvider(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -214,21 +146,19 @@ namespace Ombi HotModuleReplacement = true }); } - + app.UseHangfireServer(); app.UseHangfireDashboard("/hangfire", new DashboardOptions { - Authorization = new [] { new HangfireAuthorizationFilter() } + Authorization = new[] { new HangfireAuthorizationFilter() } }); - - // Setup the scheduler var jobSetup = (IJobSetup)app.ApplicationServices.GetService(typeof(IJobSetup)); jobSetup.Setup(); ctx.Seed(); - var provider = new FileExtensionContentTypeProvider {Mappings = {[".map"] = "application/octet-stream"}}; + var provider = new FileExtensionContentTypeProvider { Mappings = { [".map"] = "application/octet-stream" } }; app.UseStaticFiles(new StaticFileOptions() { @@ -240,7 +170,7 @@ namespace Ombi //ApiKeyMiddlewear(app, serviceProvider); app.UseMvc(routes => - { + { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); @@ -251,7 +181,6 @@ namespace Ombi }); app.UseSwaggerUI(c => { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); c.ShowJsonEditor(); }); @@ -274,7 +203,7 @@ namespace Ombi var valid = ombiSettings.ApiKey.Equals(headerKey, StringComparison.CurrentCultureIgnoreCase); if (!valid) { - context.Response.StatusCode = (int) HttpStatusCode.Unauthorized; + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; await context.Response.WriteAsync("Invalid API Key"); } else @@ -283,7 +212,7 @@ namespace Ombi identity.AddClaim(new System.Security.Claims.Claim("Origin", "Api")); identity.AddClaim(new System.Security.Claims.Claim("role", "Admin")); - var principal = new GenericPrincipal(identity, new[] {"ApiUser"}); + var principal = new GenericPrincipal(identity, new[] { "ApiUser" }); // TODO need to think about if I require a JWT Token here. context.User = principal; await next(); @@ -301,7 +230,7 @@ namespace Ombi }); } } - + public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter { public bool Authorize(DashboardContext context) diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs new file mode 100644 index 000000000..c109d8d1b --- /dev/null +++ b/src/Ombi/StartupExtensions.cs @@ -0,0 +1,96 @@ +using System; +using System.IO; +using System.Text; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.IdentityModel.Tokens; +using Ombi.Config; +using Ombi.Helpers; +using Ombi.Models.Identity; +using Swashbuckle.AspNetCore.Swagger; + +namespace Ombi +{ + public static class StartupExtensions + { + public static void AddSwagger(this IServiceCollection services) + { + services.AddSwaggerGen(c => + { + c.DescribeAllEnumsAsStrings(); + c.SwaggerDoc("v1", new Info + { + Version = "v1", + Title = "Ombi Api", + Description = "The API for Ombi, most of these calls require an auth token that you can get from calling POST:\"/connect/token/\" with the body of: \n {\n\"username\":\"YOURUSERNAME\",\n\"password\":\"YOURPASSWORD\"\n} \n" + + "You can then use the returned token in the JWT Token field e.g. \"Bearer Token123xxff\"", + Contact = new Contact + { + Email = "tidusjar@gmail.com", + Name = "Jamie Rees", + Url = "https://www.ombi.io/" + } + }); + c.CustomSchemaIds(x => x.FullName); + var basePath = PlatformServices.Default.Application.ApplicationBasePath; + var xmlPath = Path.Combine(basePath, "Swagger.xml"); + try + { + c.IncludeXmlComments(xmlPath); + } + catch (Exception e) + { + Console.WriteLine(e); + } + c.AddSecurityDefinition("Bearer", new ApiKeyScheme() + { + Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", + Name = "Authorization", + In = "header", + Type = "apiKey" + }); + + c.AddSecurityDefinition("Authentication", new ApiKeyScheme()); + c.OperationFilter(); + c.DescribeAllParametersInCamelCase(); + }); + } + + public static void AddAppSettingsValues(this IServiceCollection services, IConfigurationRoot configuration) + { + services.Configure(configuration.GetSection("ApplicationSettings")); + services.Configure(configuration.GetSection("UserSettings")); + services.Configure(configuration.GetSection("TokenAuthentication")); + services.Configure(configuration.GetSection("LandingPageBackground")); + } + + public static void AddJwtAuthentication(this IServiceCollection services, IConfigurationRoot configuration) + { + var tokenOptions = configuration.GetSection("TokenAuthentication"); + + var tokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.GetValue("SecretKey", string.Empty))), + + RequireExpirationTime = true, + ValidateLifetime = true, + ValidAudience = "Ombi", + ValidIssuer = "Ombi", + ClockSkew = TimeSpan.Zero, + }; + + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }).AddJwtBearer(x => + { + x.Audience = "Ombi"; + x.TokenValidationParameters = tokenValidationParameters; + }); + } + } +} \ No newline at end of file