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

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)
{

	// ... ... ...
	

	
	// ... ... ...
}
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:

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");
            });
        }
    }
}