123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- using System;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Security.Claims;
- using IdentityServer4.EntityFramework.DbContexts;
- using IdentityServer4.EntityFramework.Mappers;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Identity;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- using Microsoft.Net.Http.Headers;
- using Teknik.Configuration;
- using Teknik.IdentityServer.Configuration;
- using Teknik.IdentityServer.Security;
- using Teknik.IdentityServer.Middleware;
- using Teknik.Logging;
- using Microsoft.AspNetCore.Authorization;
- using Teknik.IdentityServer.Models;
- using IdentityServer4.Services;
- using System.Collections.Generic;
- using Teknik.Utilities;
-
- namespace Teknik.IdentityServer
- {
- public class Startup
- {
- public Startup(IConfiguration configuration, IHostingEnvironment env)
- {
- Configuration = configuration;
- Environment = env;
- }
-
- public IConfiguration Configuration { get; }
- public IHostingEnvironment Environment { get; }
-
- public void ConfigureServices(IServiceCollection services)
- {
- string dataDir = Configuration["ConfigDirectory"];
- AppDomain.CurrentDomain.SetData("DataDirectory", dataDir);
-
- var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
-
- // Create Configuration Singleton
- services.AddScoped<Config, Config>(opt => Config.Load(dataDir));
-
- // Build an intermediate service provider
- var sp = services.BuildServiceProvider();
-
- // Resolve the services from the service provider
- var config = sp.GetService<Config>();
-
- if (config.DevEnvironment)
- {
- Environment.EnvironmentName = EnvironmentName.Development;
- }
- else
- {
- Environment.EnvironmentName = EnvironmentName.Production;
- }
-
- services.ConfigureApplicationCookie(options =>
- {
- options.Cookie.Name = "TeknikAuth";
- options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
- options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
- options.Cookie.Expiration = TimeSpan.FromDays(30);
- options.ExpireTimeSpan = TimeSpan.FromDays(30);
- });
-
- services.AddHttpsRedirection(options =>
- {
- options.RedirectStatusCode = (Environment.IsDevelopment()) ? StatusCodes.Status307TemporaryRedirect : StatusCodes.Status308PermanentRedirect;
- #if DEBUG
- options.HttpsPort = 5050;
- #else
- options.HttpsPort = 443;
- #endif
- });
-
- // Sessions
- services.AddResponseCaching();
- services.AddMemoryCache();
- services.AddSession();
-
- // Set the anti-forgery cookie name
- services.AddAntiforgery(options =>
- {
- options.Cookie.Name = "TeknikAuthAntiForgery";
- options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
- options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
- });
-
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
-
- services.AddDbContext<ApplicationDbContext>(builder =>
- builder.UseSqlServer(config.DbConnection, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)));
-
- services.AddIdentity<ApplicationUser, IdentityRole>(options =>
- {
- options.Password = new PasswordOptions()
- {
- RequireDigit = false,
- RequiredLength = 4,
- RequiredUniqueChars = 1,
- RequireLowercase = false,
- RequireNonAlphanumeric = false,
- RequireUppercase = false
- };
- })
- .AddEntityFrameworkStores<ApplicationDbContext>()
- .AddDefaultTokenProviders();
-
- services.AddIdentityServer(options =>
- {
- options.Events.RaiseErrorEvents = true;
- options.Events.RaiseInformationEvents = true;
- options.Events.RaiseFailureEvents = true;
- options.Events.RaiseSuccessEvents = true;
- options.UserInteraction.ErrorUrl = "/Error/IdentityError";
- options.UserInteraction.ErrorIdParameter = "errorId";
- options.Cors.CorsPaths.Add(new PathString("/connect/authorize"));
- options.Cors.CorsPaths.Add(new PathString("/connect/endsession"));
- options.Cors.CorsPaths.Add(new PathString("/connect/checksession"));
- options.Cors.CorsPaths.Add(new PathString("/connect/introspect"));
- })
- .AddOperationalStore(options =>
- options.ConfigureDbContext = builder =>
- builder.UseSqlServer(config.DbConnection, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
- .AddConfigurationStore(options =>
- options.ConfigureDbContext = builder =>
- builder.UseSqlServer(config.DbConnection, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
- .AddAspNetIdentity<ApplicationUser>()
- .AddRedirectUriValidator<TeknikRedirectUriValidator>()
- .AddDeveloperSigningCredential();
-
- services.AddAuthorization(options =>
- {
- foreach (var policy in Policies.Get())
- {
- options.AddPolicy(policy.Name, p =>
- {
- foreach (var scope in policy.Scopes)
- {
- p.RequireScope(scope);
- }
- });
- }
- });
-
- services.AddAuthentication("Bearer")
- .AddIdentityServerAuthentication(options =>
- {
- options.Authority = config.UserConfig.IdentityServerConfig.Authority;
- options.RequireHttpsMetadata = true;
-
- options.ApiName = "auth-api";
- });
-
- services.AddTransient<IPasswordHasher<ApplicationUser>, TeknikPasswordHasher>();
- services.AddTransient<IProfileService, TeknikProfileService>();
- }
-
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, Config config)
- {
- // Initiate Logging
- loggerFactory.AddLogger(config);
-
- // Setup the HttpContext
- app.UseHttpContextSetup();
-
- // HttpContext Session
- app.UseSession(new SessionOptions()
- {
- IdleTimeout = TimeSpan.FromMinutes(30),
- Cookie = new CookieBuilder()
- {
- Name = "TeknikAuthSession",
- SecurePolicy = CookieSecurePolicy.Always,
- SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict
- }
- });
-
- // Use Exception Handling
- app.UseErrorHandler(config);
-
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- // Custom Middleware
- app.UseBlacklist();
- app.UseCORS();
- app.UseCSP();
- app.UseSecurityHeaders();
-
- // Cache Responses
- app.UseResponseCaching();
-
- // Force a HTTPS redirection (301)
- app.UseHttpsRedirection();
-
- // Setup static files anc cache them client side
- app.UseStaticFiles(new StaticFileOptions
- {
- OnPrepareResponse = ctx =>
- {
- ctx.Context.Response.Headers[HeaderNames.CacheControl] = "public,max-age=" + 31536000;
- }
- });
-
- InitializeDbTestDataAsync(app, config).Wait();
-
- app.UseIdentityServer();
-
- app.UseMvcWithDefaultRoute();
- }
-
- private static async System.Threading.Tasks.Task InitializeDbTestDataAsync(IApplicationBuilder app, Config config)
- {
- using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
- {
- scope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
- scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>().Database.Migrate();
- scope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
-
- var context = scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
-
- if (!context.Clients.Any())
- {
- foreach (var client in Clients.Get(config))
- {
- context.Clients.Add(client.ToEntity());
- }
- context.SaveChanges();
- }
-
- if (!context.IdentityResources.Any())
- {
- foreach (var resource in Resources.GetIdentityResources())
- {
- context.IdentityResources.Add(resource.ToEntity());
- }
- context.SaveChanges();
- }
-
- if (!context.ApiResources.Any())
- {
- foreach (var resource in Resources.GetApiResources(config))
- {
- context.ApiResources.Add(resource.ToEntity());
- }
- context.SaveChanges();
- }
- }
- }
- }
- }
|