· 6 years ago · Mar 13, 2019, 07:30 AM
1public void ConfigureServices(IServiceCollection services)
2{
3 // Deserialize specific settings into living objects
4 services.Configure<JwtSettings>(this.Configuration.GetSection("Jwt"));
5 services.Configure<CookieSettings>(this.Configuration.GetSection("Cookies"));
6
7 // Read settings to apply locally
8 DatabasesSettings dbSettings = DatabasesSettings.GetDatabasesSettings(this.Configuration);
9 JwtSettings jwtSettings = this.Configuration.GetSection("Jwt").Get<JwtSettings>();
10 CookieSettings cookieSettings = this.Configuration.GetSection("Cookies").Get<CookieSettings>();
11
12 switch (dbSettings[DatabaseConstants.DatabaseSettingsData].Provider)
13 {
14 case "mysql":
15 services.AddEntityFrameworkMySql()
16 .AddDbContext<DataContext>(options => options.UseMySql(ConnectionStringBuilder.BuildConnectionString(dbSettings[DatabaseConstants.DatabaseSettingsData])));
17 break;
18 case "mssql":
19 services.AddEntityFrameworkSqlServer()
20 .AddDbContext<DataContext>(options => options.UseSqlServer(ConnectionStringBuilder.BuildConnectionString(dbSettings[DatabaseConstants.DatabaseSettingsData])));
21 break;
22 }
23
24 // Identity MUST precede AUTHENTICATION in order to produce correct 401 Unauthorized instead of 404 Not found
25 services.AddIdentity<User, IdentityRole>(options =>
26 {
27 options.User.RequireUniqueEmail = true;
28 options.Password.RequiredLength = 6;
29 options.Password.RequireDigit = false;
30 options.Password.RequireNonAlphanumeric = false;
31 options.Password.RequireUppercase = false;
32 options.Password.RequireLowercase = false;
33 }).AddEntityFrameworkStores<DataContext>().AddDefaultTokenProviders();
34
35 // JWT Bearer Token Authentication configuration secretKey contains a secret passphrase only your server knows
36 Action<JwtBearerOptions> jwtOptions = options =>
37 {
38 options.Events = new JwtBearerEvents
39 {
40 OnTokenValidated = context =>
41 {
42 // Get the EF Context responsbile for authentication
43 DataContext dbContext = context.HttpContext.RequestServices.GetRequiredService<DataContext>();
44
45 List<Claim> claims = new List<Claim>
46 {
47 new Claim("AuthorizedAccess", "true"),
48 };
49
50 // Add claim(s) based on user -- todo
51 ClaimsIdentity appIdentity = new ClaimsIdentity(claims);
52 context.Principal.AddIdentity(appIdentity);
53
54 return Task.CompletedTask;
55 }
56 };
57 options.TokenValidationParameters = new TokenValidationParameters
58 {
59 // Do not validate lifetime. Need logout to invalidate. todo: verify if we can leave it this way
60 ValidateLifetime = jwtSettings.Expiration.Enabled,
61
62 // If you want to allow a certain amount of clock drift, set that here:
63 ClockSkew = TimeSpan.FromMinutes(jwtSettings.Expiration.ClockDrift),
64
65 // Validate the JWT Issuer (iss) claim
66 ValidateIssuer = true,
67 ValidIssuer = jwtSettings.Issuer,
68
69 // Validate the JWT Audience (aud) claim
70 ValidateAudience = true,
71 ValidAudience = jwtSettings.Audience,
72
73 // The signing key must match!
74 ValidateIssuerSigningKey = true,
75 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Key)),
76
77 SaveSigninToken = true
78 };
79 };
80 // Authentication Service
81 services.AddAuthentication(
82 options =>
83 {
84 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
85 options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
86 }).AddJwtBearer(jwtOptions).AddCookie();
87
88 // Authorization Service
89 services.AddAuthorization(
90 options =>
91 {
92 options.AddPolicy(PolicyNames.AdministrationPolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.AdministrationPolicy)));
93 options.AddPolicy(PolicyNames.PurchasePolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.PurchasePolicy)));
94 options.AddPolicy(PolicyNames.TradePolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.TradePolicy)));
95 options.AddPolicy(PolicyNames.ExchangePolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.ExchangePolicy)));
96 });
97
98 // Application Cookie
99 services.ConfigureApplicationCookie(
100 options =>
101 {
102 // Avoid redirecting REST clients on 401
103 options.Events = new CookieAuthenticationEvents
104 {
105 OnRedirectToLogin = ctx =>
106 {
107 ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
108 return Task.FromResult(0);
109 }
110 };
111
112 options.Cookie.Name = cookieSettings.ApplicationCookieName;
113 });
114
115 // Antiforgery
116 services.AddAntiforgery(
117 options =>
118 {
119 options.Cookie.Name = cookieSettings.AntiforgeryCookieName;
120 options.Cookie.Domain = cookieSettings.AntiforgeryCookieDomain;
121 options.Cookie.Path = "/";
122 options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
123 });
124
125 // Additional Services
126 services.AddSingleton<IAuthorizationHandler, AuthorizationNameHandler>();
127
128 // Cross Origin Policies
129 services.AddCors(
130 options =>
131 {
132 options.AddPolicy("AllowAnyOrigin", builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials().Build(); });
133 });
134
135 // Enable Response Compression
136 services.AddResponseCompression();
137
138 // MVC
139 services.AddMvc(
140 options =>
141 {
142 options.Filters.Add(new CorsAuthorizationFilterFactory("AllowAnyOrigin"));
143 options.CacheProfiles.Add(
144 "Default",
145 new CacheProfile()
146 {
147 Duration = 60
148 });
149 options.CacheProfiles.Add(
150 "Never",
151 new CacheProfile()
152 {
153 Location = ResponseCacheLocation.None,
154 NoStore = true
155 });
156 }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddJsonOptions(
157 options =>
158 {
159 options.SerializerSettings.Formatting = Formatting.Indented;
160 options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
161 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Error;
162 });
163
164public void Configure(IApplicationBuilder app, IHostingEnvironment env)
165{
166 if (Program.IsDebug)
167 {
168 app.UseDeveloperExceptionPage();
169 }
170 else
171 {
172 app.UseHsts();
173 }
174
175 app.UseCors("AllowAnyOrigin");
176
177 // app.UseCorsMiddleware(); // Custom middleware
178 app.UseHttpsRedirection();
179
180 app.UseDefaultFiles();
181 app.UseStaticFiles();
182 app.UseAuthentication();
183 app.UseResponseCompression();
184
185 app.UseMvc();
186}