The next generation of the Teknik Services. Written in ASP.NET. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Startup.cs 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Security.Claims;
  6. using IdentityServer4.EntityFramework.DbContexts;
  7. using IdentityServer4.EntityFramework.Mappers;
  8. using Microsoft.AspNetCore.Builder;
  9. using Microsoft.AspNetCore.Hosting;
  10. using Microsoft.AspNetCore.Http;
  11. using Microsoft.AspNetCore.Identity;
  12. using Microsoft.AspNetCore.Mvc;
  13. using Microsoft.EntityFrameworkCore;
  14. using Microsoft.Extensions.Configuration;
  15. using Microsoft.Extensions.DependencyInjection;
  16. using Microsoft.Extensions.Logging;
  17. using Microsoft.Net.Http.Headers;
  18. using Teknik.Configuration;
  19. using Teknik.IdentityServer.Configuration;
  20. using Teknik.IdentityServer.Security;
  21. using Teknik.IdentityServer.Middleware;
  22. using Teknik.Logging;
  23. using Microsoft.AspNetCore.Authorization;
  24. using Teknik.IdentityServer.Models;
  25. using IdentityServer4.Services;
  26. namespace Teknik.IdentityServer
  27. {
  28. public class Startup
  29. {
  30. public Startup(IConfiguration configuration, IHostingEnvironment env)
  31. {
  32. Configuration = configuration;
  33. Environment = env;
  34. }
  35. public IConfiguration Configuration { get; }
  36. public IHostingEnvironment Environment { get; }
  37. public void ConfigureServices(IServiceCollection services)
  38. {
  39. string dataDir = Configuration["ConfigDirectory"];
  40. AppDomain.CurrentDomain.SetData("DataDirectory", dataDir);
  41. var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
  42. // Create Configuration Singleton
  43. services.AddScoped<Config, Config>(opt => Config.Load(dataDir));
  44. // Build an intermediate service provider
  45. var sp = services.BuildServiceProvider();
  46. // Resolve the services from the service provider
  47. var config = sp.GetService<Config>();
  48. services.ConfigureApplicationCookie(options =>
  49. {
  50. options.Cookie.Name = "TeknikAuth";
  51. options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
  52. options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
  53. options.Cookie.Expiration = TimeSpan.FromDays(30);
  54. options.ExpireTimeSpan = TimeSpan.FromDays(30);
  55. });
  56. services.AddHttpsRedirection(options =>
  57. {
  58. options.RedirectStatusCode = StatusCodes.Status301MovedPermanently;
  59. });
  60. // Sessions
  61. services.AddResponseCaching();
  62. services.AddMemoryCache();
  63. services.AddSession();
  64. // Set the anti-forgery cookie name
  65. services.AddAntiforgery(options =>
  66. {
  67. options.Cookie.Name = "TeknikAuthAntiForgery";
  68. options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
  69. options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
  70. });
  71. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  72. services.AddDbContext<ApplicationDbContext>(builder =>
  73. builder.UseSqlServer(config.DbConnection, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)));
  74. services.AddIdentity<ApplicationUser, IdentityRole>(options =>
  75. {
  76. options.Password = new PasswordOptions()
  77. {
  78. RequireDigit = false,
  79. RequiredLength = 4,
  80. RequiredUniqueChars = 1,
  81. RequireLowercase = false,
  82. RequireNonAlphanumeric = false,
  83. RequireUppercase = false
  84. };
  85. })
  86. .AddEntityFrameworkStores<ApplicationDbContext>()
  87. .AddDefaultTokenProviders();
  88. services.AddIdentityServer(options =>
  89. {
  90. options.Events.RaiseErrorEvents = true;
  91. options.Events.RaiseInformationEvents = true;
  92. options.Events.RaiseFailureEvents = true;
  93. options.Events.RaiseSuccessEvents = true;
  94. options.UserInteraction.ErrorUrl = "/Error/IdentityError";
  95. options.UserInteraction.ErrorIdParameter = "errorId";
  96. })
  97. .AddOperationalStore(options =>
  98. options.ConfigureDbContext = builder =>
  99. builder.UseSqlServer(config.DbConnection, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
  100. .AddConfigurationStore(options =>
  101. options.ConfigureDbContext = builder =>
  102. builder.UseSqlServer(config.DbConnection, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
  103. .AddAspNetIdentity<ApplicationUser>()
  104. .AddRedirectUriValidator<TeknikRedirectUriValidator>()
  105. .AddDeveloperSigningCredential();
  106. services.AddAuthorization(options =>
  107. {
  108. foreach (var policy in Policies.Get())
  109. {
  110. options.AddPolicy(policy.Name, p =>
  111. {
  112. foreach (var scope in policy.Scopes)
  113. {
  114. p.RequireScope(scope);
  115. }
  116. });
  117. }
  118. });
  119. services.AddAuthentication("Bearer")
  120. .AddIdentityServerAuthentication(options =>
  121. {
  122. options.Authority = config.UserConfig.IdentityServerConfig.Authority;
  123. options.RequireHttpsMetadata = true;
  124. options.ApiName = "auth-api";
  125. });
  126. services.AddTransient<IPasswordHasher<ApplicationUser>, TeknikPasswordHasher>();
  127. services.AddTransient<IProfileService, TeknikProfileService>();
  128. }
  129. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, Config config)
  130. {
  131. // Initiate Logging
  132. loggerFactory.AddLogger(config);
  133. // Setup the HttpContext
  134. app.UseHttpContextSetup();
  135. // HttpContext Session
  136. app.UseSession(new SessionOptions()
  137. {
  138. IdleTimeout = TimeSpan.FromMinutes(30),
  139. Cookie = new CookieBuilder()
  140. {
  141. Domain = null,
  142. Name = "TeknikAuthSession",
  143. SecurePolicy = CookieSecurePolicy.Always,
  144. SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict
  145. }
  146. });
  147. // Use Exception Handling
  148. app.UseErrorHandler(config);
  149. if (env.IsDevelopment())
  150. {
  151. app.UseDeveloperExceptionPage();
  152. }
  153. // Custom Middleware
  154. app.UseBlacklist();
  155. app.UseCORS();
  156. app.UseCSP();
  157. app.UseSecurityHeaders();
  158. // Cache Responses
  159. app.UseResponseCaching();
  160. // Force a HTTPS redirection (301)
  161. app.UseHttpsRedirection();
  162. // Setup static files anc cache them client side
  163. app.UseStaticFiles(new StaticFileOptions
  164. {
  165. OnPrepareResponse = ctx =>
  166. {
  167. ctx.Context.Response.Headers[HeaderNames.CacheControl] = "public,max-age=" + 31536000;
  168. }
  169. });
  170. InitializeDbTestDataAsync(app, config).Wait();
  171. app.UseIdentityServer();
  172. app.UseMvcWithDefaultRoute();
  173. }
  174. private static async System.Threading.Tasks.Task InitializeDbTestDataAsync(IApplicationBuilder app, Config config)
  175. {
  176. using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
  177. {
  178. scope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
  179. scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>().Database.Migrate();
  180. scope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
  181. var context = scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
  182. if (!context.Clients.Any())
  183. {
  184. foreach (var client in Clients.Get(config))
  185. {
  186. context.Clients.Add(client.ToEntity());
  187. }
  188. context.SaveChanges();
  189. }
  190. if (!context.IdentityResources.Any())
  191. {
  192. foreach (var resource in Resources.GetIdentityResources())
  193. {
  194. context.IdentityResources.Add(resource.ToEntity());
  195. }
  196. context.SaveChanges();
  197. }
  198. if (!context.ApiResources.Any())
  199. {
  200. foreach (var resource in Resources.GetApiResources(config))
  201. {
  202. context.ApiResources.Add(resource.ToEntity());
  203. }
  204. context.SaveChanges();
  205. }
  206. }
  207. }
  208. }
  209. }