A bit old but very nice walk-through of important aspects on implementing a secure password reset feature.
The most common way to hash passwords for storage in .NET is using PBKDF2 via the Rfc2898DeriveBytes class. Actually, you might be doing it using System.Web.Helpers.Crypto, which internally uses the aforementioned class.
The Rfc2898DeriveBytes class has been around since (I think) .NET 2.0 and it always uses HMAC-SHA1 internally. On the other hand, the Crypto class – which is convenient because it returns the final base 64 string – uses a fixed iteration count of 1000. By now we should be using at least HMAC-SHA256 and 80K+ iterations on PBKDF2! It’s worth pointing that there are open source versions that allow us to change the iteration count and try to select the appropriate number of iterations accordingly to the current year.
As part of ASP.NET 5 development there is a new KeyDerivation class which includes a method for PBKDF2 that allows us to customize the HMAC and iteration count. The HMAC options are still a fixed enum, but at least HMAC-SHA256 and –SHA512 are available. Similar to System.Web’s Crypto class, ASP.NET 5 Identity includes a new PasswordHasher class that wraps KeyDerivation in a convenient way. It always uses HMAC-SHA256 but this time the iteration count is configurable.
Despite being on the DataProtection repository, these new key-derivation classes are available on a dedicated, self-contained package (still on pre-release). Let’s wait for the final version!
More info on ASP.NET documentation.
On the previous post I covered the application bootstrap on ASP.NET Hosting, including the Startup class and middleware configuration. The last major task on the hosting layer was to start the server using the IServerFactory located during the bootstrap. Its Start method is defined as follows:
IDisposable Start( IServerInformation serverInformation, Func<IFeatureCollection, Task> application );
I’d like to focus on the second parameter, which is function that represents the application, i.e. a callback that handles incoming requests. This function gets an IFeatureCollection and returns a Task that completes when the request processing is done. So what is this feature collection?
After the server is started, it invokes the application function each time a new request comes in. The request surfaces the application as a set of feature interfaces, which are fine-grained representations of the capabilities exposed by the server for the current request. There are feature interfaces to represent the HTTP connection, the request, the response, and so on. For instance, the interface for the HTTP response is defined as follows:
public interface IHttpResponseFeature { int StatusCode { get; set; } string ReasonPhrase { get; set; } IDictionary<string, string[]> Headers { get; set; } Stream Body { get; set; } bool HeadersSent { get; } void OnSendingHeaders(Action callback, object state); void OnResponseCompleted(Action callback, object state); }
If you recall from the previous post, the RequestDelegate gets an HttpContext and returns a Task. It is the hosting layer’s responsibility to wrap the low-level feature interfaces exposed by the server in a higher-level, strongly-typed HttpContext. This becomes clear if we take a look at the callback supplied to the server by the hosting layer:
RequestDelegate application = // ... var contextFactory = _applicationServices.GetRequiredService(); var contextAccessor = _applicationServices.GetRequiredService(); var server = ServerFactory.Start(_serverInstance, async features => { var httpContext = contextFactory.CreateHttpContext(features); // ... contextAccessor.HttpContext = httpContext; await application(httpContext); });
The HttpContext itself is an abstraction for applications to build on. The IHttpContextFactory implementation creates instances of DefaultHttpContext, which in turn uses DefaultHttpRequest and DefaultHttpResponse. These classes contain the logic of mapping feature interfaces into the high-level APIs. For example, the User property of DefaultHttpContext actually uses an underlying authentication feature:
public override ClaimsPrincipal User { get { var user = this.HttpAuthenticationFeature.User; if (user == null) { user = new ClaimsPrincipal(new ClaimsIdentity()); this.HttpAuthenticationFeature.User = user; } return user; } set { this.HttpAuthenticationFeature.User = value; } }
The two sets of abstractions – feature interfaces and HTTP abstractions – allow applications to be hosted on different servers and different servers to be used without being tied to one specific hosting model, as illustrated below.
As an example, here’s the set of feature interfaces that reach the hosting layer in my hello world example. You can see that all the implementations are on the WebListener namespace and that there is no ITlsConnectionFeature, for example.
Finally, when the request delegate is invoked, we’re immediately executing middlewares’ code. There’s literally nothing else on the way of the request! Pretty slim, right?
And that’s it for this series. I covered the execution of a self-hosted ASP.NET application, from the runtime native hosts up to the ASP.NET hosting layer and request processing. The framework code seems well organized and reduced to the essential. One can tell it was written from scratch 🙂 The one thing that seems a bit worse is how they (ab)used the service locator (despite mostly limited to the internal code) and how the conforming container (IServiceProvider interface) surfaces to the application developer.
I’ll probably dive into some details of MVC 6 on a future series. Stay tuned!
On a previous post we saw how DNX’s Application Host is responsible for adding support for the new project structure, namely assembly loading and command handling. The last step on that layer is invoking the application layer itself, which in our case is ASP.NET.
In order to find ASP.NET’s entry point, DNX Application Host uses the same logic used on the Managed Entry Point, i.e. it tries to find a Program class with a Main method. In this case, the Program class on Microsoft.AspNet.Hosting is the entry point. This layer is responsible for configuring the ASP.NET application and, ultimately, start the web server. The code on the entry point is pretty straight forward:
public void Main(string[] args) { // ... var builder = new ConfigurationBuilder(appBasePath); // ... builder.AddEnvironmentVariables(); builder.AddCommandLine(args); var config = builder.Build(); var host = new WebHostBuilder(_serviceProvider, config).Build(); using (host.Start()) { Console.WriteLine("Started"); var appShutdownService = host.ApplicationServices.GetRequiredService(); Console.CancelKeyPress += delegate { appShutdownService.RequestShutdown(); }; appShutdownService.ShutdownRequested.WaitHandle.WaitOne(); } }
The first task is to create a Configuration object, loading configuration data from environment variables and command line. The configuration system is completely different in the version of ASP.NET. Web.config is gone; configuration settings are loaded from different sources, such as environment variables and JSON files, and made available via a common interface. In our case, we can see in debug that the server configuration parameters were loaded from the command line.
The next step is to create a IHostingEngine via the WebHostBuilder and start it. This is where all the core logic of configuring the application resides (more on this soon). Finally, since we’re self hosting, a callback is registered to request application shutdown when CTRL + C is pressed and the host waits for that event.
Before going into more details, lets just recap a few concepts:
public delegate Task RequestDelegate(HttpContext context);
public class Startup { public void Configure(IApplicationBuilder app) { app.Use(next => httpContext => { httpContext.Response.Headers.Append("Debug", "Hello world!"); return next(httpContext); }); // Run just ignores the "next" paramater (end of the pipeline) app.Run(ctx => ctx.Response.WriteAsync("Hello ASP.NET 5 world! Time: " + DateTime.Now)); } }
For more information, I’ve explained these components a while ago on my Hello World posts; also I found this post that explains the “pipeline” details pretty well.
Back to the code, the WebHostBuilder class is responsible for creating an IHostingEngine that can be used to start the application/server. Following the builder pattern, the class has a set of methods to configure the hosting engine that will be built, namely to explicitly define the startup and server types:
When none of these methods are used, the class uses the built-in default logic, such as getting the server name from configuration and trying to find a Startup class on the application assembly. This is actually the case on the self hosting scenario, as we saw above. On other hosting scenarios, some explicit configurations may take place.
Going into the Build method, we can see that the first step is to register some hosting services that will be required further on:
services.AddTransient<IStartupLoader, StartupLoader>(); services.AddTransient<IServerLoader, ServerLoader>(); services.AddTransient<IApplicationBuilderFactory, ApplicationBuilderFactory>(); services.AddTransient<IHttpContextFactory, HttpContextFactory>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
For now I’d like to highlight the following of those services:
These and other already configured services are passed to HostingEngine and the server and startup types are set accordingly to the builder methods. Note the usage of the configuration to get the server assembly as a fallback.
var startupLoader = hostingContainer.GetRequiredService(); // ... var engine = new HostingEngine(hostingServices, startupLoader, _config); // Only one of these should be set, but they are used in priority engine.ServerFactory = _serverFactory; engine.ServerFactoryLocation = _config.Get(ServerKey) ?? _serverFactoryLocation; // Only one of these should be set, but they are used in priority engine.Startup = _startup; engine.StartupType = _startupType; engine.StartupAssemblyName = _config.Get(ApplicationKey) ?? appEnvironment.ApplicationName; return engine;
The HostingEngine is the class responsible for actually starting the server and defining how requests are handed to the application. When the Start method is invoked the following major steps are executed in order to get the server/application running:
1. Find Startup class and configuration methods
In this step, the IStartupLoader mentioned before is used. There are two parts: the first is to lookup the Startup class, if not explicitly defined on the WebHostBuilder; the second is to lookup the Configure method on that class.
if (Startup != null) { return; } if (StartupType == null) { // ... StartupType = _startupLoader.FindStartupType(StartupAssemblyName, diagnosticTypeMessages); // ... } Startup = _startupLoader.LoadMethods(StartupType, diagnosticMessages);
On the FindStartupType method is worth mentioning that the actual startup type can be named Startup or StartupXXXX, where XXXX is the environment name (e.g. StartupProduction). This allows you to have different startup classes per deployment environment.
The LoadMethods method is responsible for finding the Configure method on the startup class. In addition it searches for an optional ConfigureServices method, which can be used to register services on the DI infrastructure (I’ve deliberately omitted this method up until now). These methods can also have environment dependent names: ConfigureXXXX and ConfigureXXXXServices, where XXXX is the environment name. The following structure is returned to represent these configuration methods:
public class StartupMethods { // ... public Func ConfigureServicesDelegate { get; } public Action ConfigureDelegate { get; } }
2. Configure application services on DI infrastructure
Having the configuration methods, ASP.NET allows the application to register its services and possibly return a different IServiceProvider:
_applicationServices = Startup.ConfigureServicesDelegate(_applicationServiceCollection);
When the startup class doesn’t define a ConfigureServices method, there’s a default that simply builds the IServiceProvider from the current service collection.
3. Load and initialize the IServerFactory
if (ServerFactory == null) { ServerFactory = _applicationServices .GetRequiredService() .LoadServerFactory(ServerFactoryLocation); } _serverInstance = ServerFactory.Initialize(_config);
Recall that on our example the ServerFactoryLocation was supplied via command line to the WebHostBuilder in the first place.
4. Create the application middlewares chain
From the framework point-of-view, creating the middleware chain/pipeline is simple:
var builderFactory = _applicationServices.GetRequiredService(); var builder = builderFactory.CreateBuilder(_serverInstance); var configure = Startup.ConfigureDelegate; // ... configure(builder);
However, I’d like to highlight a few aspects around IApplicationBuilder. This interface is very simplistic when it comes to registering middlewares:
public interface IApplicationBuilder { // ... IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); RequestDelegate Build(); }
On the example Startup class shown before, the Use method is invoked directly. There’s, however, a UseMiddleware() extension method that’s worth mentioning, because it includes the convention to find a RequestDelegate on the middleware type:
public static IApplicationBuilder UseMiddleware(this IApplicationBuilder builder, Type middleware, params object[] args) { var applicationServices = builder.ApplicationServices; return builder.Use(next => { var instance = ActivatorUtilities.CreateInstance(builder.ApplicationServices, middleware, new[] { next }.Concat(args).ToArray()); (1) var methodinfo = middleware.GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public); (2) var parameters = methodinfo.GetParameters(); if (parameters[0].ParameterType != typeof(HttpContext)) (3) { throw new Exception("Middleware Invoke method must take first argument of HttpContext"); } if (parameters.Length == 1) { return (RequestDelegate)methodinfo.CreateDelegate(typeof(RequestDelegate), instance); } // ... }); }
The extension method registers an “inline middleware” that instantiates the supplied middleware type (1) and lookups a method named Invoke (2) which gets an HttpContext as the first parameter (3). This method is used as the middleware’s RequestDelegate. An important detail is that the “next” RequestDelegate is passed as an argument when creating an instance of the middleware, allowing it to eventually invoke the next element on the pipeline. An example of a middleware compliant with this convention is:
public class GotchaMiddleware { private readonly RequestDelegate _next; public GotchaMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { await _next(httpContext); await httpContext.Response.WriteAsync(" GOTCHA!"); } }
5. Build the final RequestDelegate
After the ConfigureDelegate is invoked, the ApplicationBuilder contains an ordered list of middlewares, as shown below. This screenshot corresponds to the Startup class shown before with an additional call to UseMiddleware().
The first middleware is added internally to handle per-request DI stuff; the others are the ones registered by the application. We can match the anonymous functions type names shown on the debugger to the code on the Startup class: one inside the Configure method, one inside the Run extension method and another inside the UseMiddleware extension method. This corresponds to the three middlewares registered on the Startup class.
The next task of HostingEngine is to invoke the ApplicationBuilder Build method in order to create the final RequestDelegate. Recall that a middleware is a function that composes a RequestDelegate around another (the next one in the chain). Therefore, the final RequestDelegate must be built from the last middleware to the first, as illustrated below.
The code on the Build method does exactly that: reverses the middleware list and invokes them one by one, passing the current RequestDelegate. To bootstrap the configuration, HostingEngine uses a default RequestDelegate that returns an HTTP 404 status code, ensuring a default response when no other middleware handles the request.
public RequestDelegate Build() { RequestDelegate app = context => { context.Response.StatusCode = 404; return Task.FromResult(0); }; foreach (var component in _components.Reverse()) { app = component(app); } return app; }
6. Start the server
Finally, the server is started using the IServerFactory previously created and the HostingEngine returns a disposable that allows shutting down the server.(used by the Main method all the way up to the start of this post). To start the server, the HostingEngine supplies a callback that handles incoming requests. Naturally, this callback uses the RequestDelegate built on the previous step.
var server = ServerFactory.Start(_serverInstance, async features => { var httpContext = // ... // ... await application(httpContext); }); _applicationLifetime.NotifyStarted(); return new Disposable(() => { _applicationLifetime.NotifyStopping(); server.Dispose(); _applicationLifetime.NotifyStopped(); });
I’ll cover the request handling callback on the next post (the last on this series). Stay tuned!
On the previous post of this series we got to the point where DNX invokes ASP.NET code. While I already had DNX code on VS, I guess from now on it’ll be more important (fun?) to debug and see things happening, so I’ll recap the debug setup before moving further. I’ve cover this on part I and part II of the series but things are a bit fragmented. Also, I was based beta 4 releases of the different components; that was 2 months ago, so I’ll be moving into the latest versions (release branch versions, actually, which seem to be on beta 6 by now). So, here’s what I did:
git clone https://github.com/aspnet/Mvc.git -b release
dnvm update-self
dnvm upgrade -r clr -unstable
dnvm upgrade -r coreclr -unstable
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using System;
namespace HelloWorld.Web
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(ctx => ctx.Response.WriteAsync("Hello ASP.NET 5 world! Time: " + DateTime.Now));
}
}
}
{
"webroot": "wwwroot",
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-beta-*",
"Microsoft.AspNet.Mvc": "6.0.0-beta-*",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta-*",
"Microsoft.AspNet.StaticFiles": "1.0.0-beta-*"
},
"commands": {
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000"
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
}
}
dnu restore
dnx . web
This should launch the server. Try navigating to the URL configured on the project file. Then:
{
"projects": [
"src",
"C:/aspnet-source/hosting/src",
"C:/aspnet-source/mvc/src",
"C:/aspnet-source/http-abstractions/src"
],
"sdk": {
"version":"1.0.0-beta6-11944"
}
}
VS should start restoring dependencies and adding the projects found on the ASP.NET sources to the solution. If not, try closing and reopening the solution.
That’s it! You can now debug into ASP.NET code. I’ll go into this code on the following posts.