Author : MD TAREQ HASSAN
Startup class
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// register services to make available to app (DI, to use in Configure() etc.)
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// hook into pipeline, configures if needed
}
MVC controllers
- For most apps, calls to UseAuthentication, UseAuthorization, and UseCors must appear between the calls to UseRouting and UseEndpoints to be effective.
- https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.mvcservicecollectionextensions
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.AddControllersWithViews()
// ... ... ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... ... ...
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
//endpoints.MapDefaultControllerRoute();
//endpoints.MapDefaultControllerRoute().RequireAuthorization();
});
// ... ... ...
}
Razor pages
public class Startup
{
// ... ... ...
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... ... ....
app.UseRouting();
// AuthN & AuthZ config. here
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
Options
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.RootDirectory = "/MyPages";
options.Conventions.AuthorizeFolder("/MyPages/Admin");
});
}
Details: https://docs.microsoft.com/en-us/aspnet/core/razor-pages/#advanced-configuration-and-settings
Logging
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.AddLogging(config =>
{
// clear out default configuration
config.ClearProviders();
//config.AddConfiguration(Configuration.GetSection("Logging"));
//config.AddDebug();
//config.AddEventSourceLogger();
//if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == EnvironmentName.Development)
//{
// config.AddConsole();
//}
});
}
Authentication
ID & Password Login (Identity + EF Core Store)
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.AddDbContextPool<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>(options =>
{
options.SignIn.RequireConfirmedAccount = true;
// add more options here
});
services.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication();
// ... ... ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... ... ...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
endpoints.MapRazorPages();
});
}
OpenID Connect
services.AddAuthentication(options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options => {
options.LoginPath = "/Account/Login/";
})
.AddOpenIdConnect(options =>
{
options.ClientId = Configuration["oidc:clientid"];
options.ClientSecret = Configuration["oidc:clientsecret"];
options.Authority = ""
options.ResponseType = "code";
options.GetClaimsFromUserInfoEndpoint = true;
}
);
Redirect
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Events.OnRedirectToAccessDenied = ReplaceRedirector(HttpStatusCode.Forbidden, options.Events.OnRedirectToAccessDenied);
options.Events.OnRedirectToLogin = ReplaceRedirector(HttpStatusCode.Unauthorized, options.Events.OnRedirectToLogin);
});
}
// More
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = ".AspNetCoreIdentityCookie";
options.Events.OnRedirectToLogin = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 403;
return Task.CompletedTask;
};
});
Authorization
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
// Authentication code here
// i.e. AddDbContextPool, AddDefaultIdentity, AddEntityFrameworkStores, AddAuthentication() etc.
services.AddAuthorization(o => o.AddPolicy(_RequireAuthenticatedUserPolicy, builder => builder.RequireAuthenticatedUser()));
// or
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
// ... ... ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... ... ...
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute().RequireAuthorization(_RequireAuthenticatedUserPolicy);
endpoints.MapRazorPages();
});
// or
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute().RequireAuthorization();
endpoints.MapRazorPages();
});
}
Password settings
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
}
// ... ... ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... ... ...
// ... ... ...
}
Lockout settings
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.Configure<IdentityOptions>(options =>
{
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
}
// ... ... ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... ... ...
// ... ... ...
}
User settings
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.Configure<IdentityOptions>(options =>
{
// User settings.
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
}
// ... ... ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... ... ...
// ... ... ...
}
Cookie settings
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = "/Identity/Account/Login";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
options.SlidingExpiration = true;
});
// ... ... ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... ... ...
app.UseCookiePolicy();
// ... ... ...
}
Cache settings
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
var connectionString = @"...";
services.AddDistributedSqlServerCache(opt =>
{
opt.ConnectionString = connectionString;
opt.SchemaName = "dbo";
opt.TableName = "SQLCache";
});
// ... ... ...
}
See:
- https://aspnetcore.readthedocs.io/en/stable/performance/caching/distributed.html
- https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed
- https://github.com/dotnet/AspNetCore.Docs/blob/master/aspnetcore/performance/caching/distributed.md
LoggedIn User info using HttpContext
public void ConfigureServices(IServiceCollection services)
{
//services.AddRazorPages();
//services.AddServerSideBlazor();
// ... ... ...
// for getting loggedin user
services.AddHttpContextAccessor();
// ... ... ...
}
Usage
// Extension method
public static string GetLoggedInUser(this IHttpContextAccessor httpContextAccessor)
{
//
// Currently (as of August, 2020) AspNetCore does not populate identity info. if,
// Authentication & Authorization are implemented at Azure App Service level
// But, HttpContext.User.Claims will be available by a custom middleware
//
var username = httpContextAccessor.HttpContext.User.Identity.Name;
if (string.IsNullOrWhiteSpace(username))
{
Log.Debug("No user found!");
return "Foo";
}
Log.Debug($"Loggedin user: {username}");
return username;
}
// Using in service
public class FooService : IFooService
{
// ... ... ...
private readonly IHttpContextAccessor _httpContextAccessor;
public EmailService(IHttpContextAccessor httpContextAccessor)
{
// ... ... ...
_httpContextAccessor = httpContextAccessor;
// ... ... ...
}
public async Task<bool> SaveEditedDataAsync(EditModel editModel)
{
int affectedRows = -1;
try
{
var trackedEntity = await _dbContext.Foos.FindAsync(editModel.Id);
// ... ... ...
trackedEntity.ModifiedBy = _httpContextAccessor.GetLoggedInUser();
affectedRows = await _dbContext.SaveChangesAsync();
}
catch (Exception ex)
{
Log.Error(ex.Message, ex);
}
return affectedRows >= 1;
}
// ... ... ...
}
SignalR
// ... ... ...
using SignalRChat.Hubs;
namespace SignalRChat
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... ... ...
app.UseRouting();
// ... ... ...
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapHub<ChatHub>("/chatHub");
});
}
}
}