Configuration

ASP.NET Core Password Options and Custom Validators

ASP.NET Core provides a lot of identity feature out of the box when individual user accounts is selected during project creation. Using the default settings a user’s password is required to be at least 6 characters and contain a number, a lower case letter, an uppercase letter and a special character. This post is going to cover changing the the above options as well as creating custom validators.

Password Options

The following is the default registration of identity in the ConfigureServices  function of the Startup  class with the default settings mentioned above.

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

AddIdentity  can accept options part of which allows control over the basic characteristics of what is required for user passwords. Here is the same AddIdentity but with all the options for passwords listed.

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonLetterOrDigit = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
})
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

All the options do what you would expect. One thing to note is if you change the required length by setting options.Password.RequiredLength then the new setting will only be validated on post back to the server, which is the case of most password validation anyway, but for pre-post validation on length then the string length data annotation needs to be updated on RegisterViewModel.PasswordResetPasswordViewModel.PasswordChangePasswordViewModel.NewPassword and SetPasswordViewModel.NewPassword.

Custom Password Validators

The above is great for changing simple aspects of password validation, but we all know password rules for organizations are not always simple enough to be covered by the above. Thankfully Microsoft has provided the AddPasswordValidator  extension method to the IdentityBuilder class which is what is returned by AddIdentity.

AddPasswordValidator takes a type that implements IPasswordValidator. The custom validator only has to implement the  ValidateAsync defined by IPasswordValidator. The following validator checks to make sure that all the characters of the password are not the same and returns an IdentityResult based on the conditions passing. Forgive the contrived example, but I wanted to keep the class as simple as possible.

public class SameCharacterPasswordValidator<TUser>: IPasswordValidator<TUser> 
       where TUser : class
{
    public Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, 
                                              TUser user, 
                                              string password)
    {
        return Task.FromResult(password.Distinct().Count() == 1 ? 
            IdentityResult.Failed(new IdentityError
            {
                Code = "SameChar",
                Description = "Passwords cannot be all the same character."
            }) : 
            IdentityResult.Success);
    }
}

If validation failed is the result then is added to the list of validation messages the user sees just like with the built in password validations.

Here is registration of identity with the custom password validation which is on the last line.

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonLetterOrDigit = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
})
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddPasswordValidator<SameCharacterPasswordValidator<ApplicationUser>>();

Potential Use

Imagine you have a requirement to make sure a user doesn’t reuse the same password for a period of time. This would be a great place for a custom password validator. You could use dependency injection to get reference to a history of password hashes and use that to verify the user is not repeating the same password. Of course would have to first write the password hash history.

Dependency Injection Conditional Registration in ASP.NET Core

Now that I know emailing and SMS are working I wanted a way to get the information from the out going messages without actually hitting a third party service or having to use break points. To do this I wrote a new class that implemented IEmailSender and ISmsSender that wrote the messages to a file instead of hitting Mailgun and Twilio.

Dependency Injection (DI)

ASP.NET Core comes with dependency injection built-in the details of which are described in the docs and the code can be found here. The docs article does a great job of explaining DI so I am going to keep my description limited to the example at hand.

In ASP.NET Core services are registered in the ConfigureServices of the StartUp class. When an application first starts running the StartUp constructor runs followed by ConfigureServices and finally Configure.

Configuration Based Services

One potential way to handle decisions on which services to register is via configuration settings.  Using the following configuration as an example if WriteToFile is true then the file writer version of the email service should be used instead of the version that actually emails users.

{
  "EmailSettings": {
    "WriteToFile": true,
    "Path": "C:\Email\"
  }
}

With this configuration in place ConfigureServices uses the following to load the proper service based on the config value.

if (Configuration.Get<bool>("EmailSettings:WriteToFile"))
{
    services.AddTransient<IEmailSender, AuthMessageSenderFileWriter>();
}
else
{
    services.AddTransient<IEmailSender, AuthMessageSender>();
}

Environment Based Services

ASP.NET Core’s IHostingEnvironment defines an EnvironmentName which automatically gets loaded by the host from an environment variable. To quote Visual Studio’s Object Browser on EnvironmentName:

Gets or sets the name of the environment. This property is automatically set by the host to the value of the “Hosting:Environment” (on Windows) or “Hosting__Environment” (on Linux & OS X) environment variable.

I found this post by Armen Shimoon which clued me in on the fact that ConfigureServices is only called ASP.NET Core if no Configure{EnvironmentName}Services is found. This means that if EnviromentName is set to Development then ConfigureDevelopmentServices will be called instead of ConfigureServices. Extensions are provided out of the box to help support Development, Staging and Production values.

For development runs of the application to write to a file instead of emailing I added a ConfigureDevelopmentServices.

public void ConfigureDevelopmentServices(IServiceCollection services)
{
    ConfigureServices(services);
    services.AddTransient<IEmailSender, AuthMessageSenderFileWriter>();
}

The first thing this function does is to call ConfigureServices since that is where the majority of service registrations is done. ConfigureServices registers an IEmailSender with AuthMessageSender, but that registration is overwritten with AuthMessageSenderFileWriter in ConfigureDevelopmentServices after the ConfigureServices function returns.

Final Thoughts

I have presented a couple of ways to handled varying registrations with ASP.NET Core’s built in dependency injection. I see using the ability to run different version of ConfigureServices to be the one I will get the most use out of, but I am sure basing the decision off of configuration could come in handy as well.

If you know of other options please leave a comment.

SMS using Twilio Rest API in ASP.NET Core

A couple of weeks ago I went over using email in ASP.NET Core which left the provided MessageService class half implemented.  This post is going to cover the implementation of the other MessageService function that is used to send SMS as part of two-factor authentication.

View

In Views/Manage/Index.cshtml uncomment the following to enable the UI bit associated with phone numbers.

@(Model.PhoneNumber ?? "None")
    @if (Model.PhoneNumber != null)
    {
        <br />
        <text>[&nbsp;&nbsp;<a asp-controller="Manage" asp-action="AddPhoneNumber">Change</a>&nbsp;&nbsp;]</text>
        <form asp-controller="Manage" asp-action="RemovePhoneNumber" method="post" role="form">
            [<button type="submit" class="btn-link">Remove</button>]
        </form>
    }
    else
    {
        <text>[&nbsp;&nbsp;<a asp-controller="Manage" asp-action="AddPhoneNumber">Add</a>&nbsp;&nbsp;]</text>
    }

And this as well.

@if (Model.TwoFactor)
    {
        <form asp-controller="Manage" asp-action="DisableTwoFactorAuthentication" method="post" class="form-horizontal" role="form">
            Enabled [<button type="submit" class="btn-link">Disable</button>]
        </form>
    }
    else
    {
        <form asp-controller="Manage" asp-action="EnableTwoFactorAuthentication" method="post" class="form-horizontal" role="form">
            [<button type="submit" class="btn-link">Enable</button>] Disabled
        </form>
    }

Twilio

I spend a lot of time trying to find a services that allows sending of SMS for free and had zero luck. I ended up going with  Twilio as they do provide free messaging with their trial account. The usage section of the web site will make it looking like you will be changed, but that is just to provide an idea of what the service would cost and will not actually be charged.

Storing Configuration

Just as a couple of weeks ago for EmailSetting I created a SmsSettings class that will be loaded from user secrets in the StartUp class of the application. For more details on general configuration in ASP.NET Core check out this post and then this post for more details on user secrets. The following is my SMS settings class.

public class SmsSettings
{
    public string Sid { get; set; }
    public string Token { get; set; }
    public string BaseUri { get; set; }
    public string RequestUri { get; set; }
    public string From { get; set; }
}

And this is the config file looks like with the curly braces needed to be replace with values from your Twilio account. For example if your Twilio phone number was 15554447777 then the from line would be: “From”: “+15554447777”

{
  "SmsSettings": {
    "Sid": "{TwilioAccountSid}",
    "Token": "{TwilioAuthToken}",
    "BaseUri": "https://api.twilio.com",
    "RequestUri": "/2010-04-01/Accounts/{TwilioAccountSid}/Messages.json",
    "From": "+{TwilioPhoneNumber}"
  }
}

Then in ConfigureServices function of Startup.cs add a reference to the SmsSettings class to make it available using dependency injection.

services.Configure<SmsSettings>(Configuration.GetSection("SmsSettings"));

Message Services

In Services/MessageService.cs there is an empty implementation for sending SMS base on ISmsSender which defines a single SendSmsAsync function which is called when the application wants to send a SMS.

Add a constructor to the class if it doesn’t already have one so that the SmsSettings can be injected by the framework and add a field to store the settings in. I have removed the email related items from the constructor but you can look at this post if you want to include the email related bits a well.

private readonly SmsSettings _smsSettings;

public AuthMessageSender(IOptions<SmsSettings> smsSettings)
{
    _smsSettings = smsSettings.Value;
}

Then the SendSmsAsync function which uses the HttpClient with basic authentication and form url encoded content to make a post request to the Twilio API looks like the following.

public async Task SendSmsAsync(string number, string message)
{
    using (var client = new HttpClient { BaseAddress = new Uri(_smsSettings.BaseUri) })
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
            Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_smsSettings.Sid}:{_smsSettings.Token}")));

        var content = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("To",$"+{number}"),
            new KeyValuePair<string, string>("From", _smsSettings.From),
            new KeyValuePair<string, string>("Body", message)
        });

        await client.PostAsync(_smsSettings.RequestUri, content).ConfigureAwait(false);
    }
}

Now you application is capable of sending SMS.

ASP.NET Docs

As I was writing this I came across Rick Anderson’s post in the official docs that covers two-factor authentication. I highly recommend you read Rick’s post as he covers the UI portion in more depth than I did. Another note Rick is using the Twilio helper client were I am using the HttpClient in order to maintain dnxcore50 compatibility.

Emails using Mailgun in ASP.NET Core

Updated version of this post can be found here.

At last month’s Nashville .Net Users Group meeting Michael McCann when over some of the aspects of ASP.NET’s membership provider (non-core version). One of the things he talked about was enabling email as part of the user sign up process and for use in password recovery. This post is going to cover the same emailing aspect but in ASP.NET core using mailgun to actually send emails.

Account Controller

In the account controller most of the code needed is already present and just needs to be uncommented. In the Register function uncomment the following which will send the user an email asking that the address be confirmed. This of course stops users from signing up with email addresses they don’t actually have access to.

var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action("ConfirmEmail", 
                             "Account", 
                             new { userId = user.Id, code = code }, 
                             protocol: HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
  "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");

And then comment out this next line which would sign the user in before they have used the email above to confirm their account.

//await _signInManager.SignInAsync(user, isPersistent: false);

Next in the Login function add the following bit of code just before the call to _signInManager.PasswordSignInAsync. This looks up the user by email address and returns an error if the account has not been confirmed.

var user = await _userManager.FindByNameAsync(model.Email);
if (user != null)
{
    if (!await _userManager.IsEmailConfirmedAsync(user))
    {
        ModelState.AddModelError(string.Empty, 
                                 "You must have a confirmed email to log in.");
        return View(model);
    }
}

The last change is in the ForgotPassword function. Uncomment the following code to send the user an email to reset their password.

var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Action("ResetPassword", 
                             "Account", 
                             new { userId = user.Id, code = code }, 
                             protocol: HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, "Reset Password",
 "Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>");
return View("ForgotPasswordConfirmation");

Forgot Password View

In ForgotPassword.cshtml uncomment the following section to show the UI associated with email based password reset.

<form asp-controller="Account" asp-action="ForgotPassword" method="post" class="form-horizontal" role="form">
    <h4>Enter your email.</h4>
    <hr />
    <div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Email" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="Email" class="form-control" />
            <span asp-validation-for="Email" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <button type="submit" class="btn btn-default">Submit</button>
        </div>
    </div>
</form>

Caution for existing sites

With the changes above if a user has not confirmed their email address then they will not be able to log in or reset their password. Any existing users would need to have their accounts marked as confirmed manually by updating the EmailConfirmed bit field in the AspNetUsers table or be provided away to confirm their account.

Mailgun

Mailgun is an email service that provides a simple API for sending emails and allows up to 10,000 emails to be sent free every month. I have only used mailgun for sending test emails so I can’t speak to how it holds up at scale.

After signing up for an account click on the domains tab and select the only existing active domain which should start with something like sandbox.

Storing Configuration

In my project I created an EmailSettings class that will be loaded from user secrets in the start up of the application. For more details on general configuration in ASP.NET Core check out this post and thenthis post for more details on user secrets. The following is my email settings class.

public class EmailSettings
{
    public string ApiKey { get; set; }
    public string BaseUri { get; set; }
    public string RequestUri { get; set; }
    public string From { get; set; }
}

If using mailgun the above fields map to the following from the mailgun domain page.

EmailSettings Mailgun Example
ApiKey API Key key-*
BaseUri API Base URL https://api.mailgun.net/v3/
RequestUri API Base URL sandbox*.mailgun.org
From Default SMTP Login [email protected]*.mailgun.org

A couple of notes to the above table on what I actually saved in my config files.

EmailSettings Field Note Example
ApiKey Used with basic auth and needs username api:key-*
RequestUri Needs the API end point to call sandbox*.mailgun.org/messages

The following is what my actual config files ends up looking like.

{
  "EmailSettings": {
    "ApiKey": "api:key-*",
    "BaseUri": "https://api.mailgun.net/v3/",
    "RequestUri": "sandbox*.mailgun.org/messages",
    "From": "[email protected]*.mailgun.org"
  }
}

In the ConfigureServices function Startup.cs I added a reference to the new settings class so it would be available for dependency injection.

services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));

Message Services

In the Services folder there is a MessageServices.cs file which contains the AuthMessageSender class that has an empty implementation for sending email base on an IEmailSender interface which defines a single SendEmailAsync method. This function is already being called in the code that was uncommented above so I am going to use it to call mailgun’s API.

First I need to get the email settings defined above injected into the AuthMessageSenderClass by adding a class level field and a constructor. The only thing the constructor is doing is saving a reference to the injected settings class.

private readonly EmailSettings _emailSettings;

public AuthMessageSender(IOptions<EmailSettings> emailSettings)
{
    _emailSettings = emailSettings.Value;
}

Next is the SendEmailAsync function mentioned above which I changed to an async function and added the code to send an email using mailgun’s API.

public async Task SendEmailAsync(string email, string subject, string message)
{
    using (var client = new HttpClient { BaseAddress = new Uri(_emailSettings.BaseUri) })
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
            Convert.ToBase64String(Encoding.ASCII.GetBytes(_emailSettings.ApiKey)));

        var content = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("from", _emailSettings.From),
            new KeyValuePair<string, string>("to", email),
            new KeyValuePair<string, string>("subject", subject),
            new KeyValuePair<string, string>("text", message)
        });

        await client.PostAsync(_emailSettings.RequestUri, content).ConfigureAwait(false);
    }
}

This code is using the HttpClient to send a request to mailgun’s API using basic authorization and form url encoded content to pass the API the relevant bit of information.

With that your application will now email account conformations and password resets.

Other Email Options

Mailgun is obviously not the only option for sending emails. This post from Mashape lists 12 API providers. In addition SMTP is also an option which this post by Steve Gordon covers.

Basic Configuration with Aurelia

If you have been following my Aurelia posts using an ASP.NET 5 web API then you will have noticed that I have been hardcoding the API url. In this post I am going to cover the basics of configuration in Aurelia which will allow the API url to be in a single location instead of spread all over the application.

Configuration will be done using the Aurelia-Configuration plugin. To install open a console window and navigate to the folder that contains the application’s package.json file and run the following command.

jspm install aurelia-configuration

If you are using Visual Studio to find your package.json make sure to click the show all files button in the solution explorer. With the release of RC1 package.json is hidden by default.

First code change is in the html file that kicks off Aurelia. The changed part is on the first line with aurelia-app which changed to aurelia-app=”main”.

<div aurelia-app="main">
    <script src="../jspm_packages/system.js"></script>
    <script src="../config.js"></script>
    <script>
        System.import("aurelia-bootstrapper");
    </script>
</div>

Next add a main.js file in the wwwroot folder. This file will be called when Aurelia is bootstrapped and will control how Aurelia is bootstrapped. Everything in this file is the default Aurelia bootstrapping process other than “.plugin(‘aurelia-configuration’)” which is the part that needs to be added for configuration to work.

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging()
    .plugin('aurelia-configuration');

  aurelia.start().then(a => a.setRoot());
}

By default the configuration plugin looks for an application.json inside of a config directory in the root directory. This tripped me up a bit as I was expecting this to be a config directory inside of wwwroot, but that is not exactly the case. Root in the case means root for the Aurelia application context. In my case my Aurelia app is launched from a HomeController which means the application.json file needed to be in wwwroot/Home/config. Here is my application.json file with the base url for my test API.

{
	"api": {
		"baseUrl": "http://localhost:18907/api/"
	}
}

Now to get access to the configuration information. First add an import for configuration.

import {Configure} from 'aurelia-configuration';

Add Configure to the inject decorator.

@inject(HttpClient, Router, EventAggregator, Configure)

And to the constructor.

constructor(http, router, eventAggregator, configAurelia)

Now the actual usage of a config value with a before and after for comparison.

Before:
.withBaseUrl('https://localhost:18907/api/');

After:
.withBaseUrl(config.get('api.baseUrl'));

Here is all of the above together for reference.

import {Configure} from 'aurelia-configuration';

@inject(HttpClient, Router, EventAggregator, Configure)
export class Detail{

    constructor(http, router, eventAggregator, configAurelia){
        http.configure(config => {
            config
              .useStandardConfiguration()
              .withBaseUrl(configAurelia.get('api.baseUrl'));
        });

        this.http = http;
        this.router = router;
        this.eventAggregator = eventAggregator;
    }

That is all there is for basic configuration with Aurelia. Check out the plugin’s site for examples of how set up configurations for different environments, setting the config directory as well as filename.

Configuration in ASP.NET 5

ASP.NET 5 offer a lot of options for loading configuration data such as json files, ini files, XML files, in memory collections, command line arguments, user secrets and environment variables.

The following has at least one example of each type of configuration. Configurations are setup in the constructor of the Startup class.

public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
    // Setup configuration sources.
    var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
        .AddJsonFile("config.json")
        .AddJsonFile($"config.{env.EnvironmentName}.json", optional: true)
        .AddIniFile("config.ini", optional: true)
        .AddInMemoryCollection(new Dictionary<string, string="">
        {
            {
            "AppSettings:TagLine",
            "InMemoryCollection"
            }
        })
        .AddXmlFile("config.xml", optional:true);

    if (env.IsDevelopment())
    {
        builder.AddUserSecrets();
    }
    builder.AddEnvironmentVariables();
    Configuration = builder.Build();
}

As you can see from the example all the different configuration sources can be used together without any issues. A critical thing to keep in mind is if a configuration option is set in multiple places the last configuration source’s value will be used. For example, using the code above, if the title of a site was sent in config.json and config.ini then the value from config.ini would be used.

An example I have seen the ASP.NET team use many times is to use user secrets for API key when in development and then store the keys in environment variables for production.

Here are the relevant lines from the dependencies section of the project.json file.

"Microsoft.Framework.Configuration.Abstractions": "1.0.0-beta7",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta7",
"Microsoft.Framework.Configuration.UserSecrets": "1.0.0-beta7",
"Microsoft.Framework.Configuration.Xml" : "1.0.0-beta7"

Another great feature is being able to load an object with the values from a configuration section. The following is a class created to hold the settings for an application.

public class AppSettings
{
    public string Title { get; set; }
    public string TagLine { get; set; }
}

Then in the ConfigureServices function this is all that is needed to load the class.

services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

Now instead of directly accessing the configuration classes in the HomeController the AppSettings class can be used instead. Here is an example of using ASP.NET 5’s built-in dependency to automatically get a reference to AppSetting via constructor injection.

private readonly IOptions _appSettings;

public HomeController(IOptions appSettings)
{
    _appSettings = appSettings;
}

And then using the _appSettings in the index action to pass values to the view.

public IActionResult Index()
{
    ViewData["Title"] = $"{_appSettings.Options.Title} - " +
                        $"{_appSettings.Options.TagLine}";
    return View();
}

The above is using C# 6’s new interpolated string feature.  The dollar sign before the string is what triggers the feature and allow use variables when wrapped in curly braces.

Check out this github repo for the internals of configuration in ASP.NET 5 .

I also recommend checking out the new Introduction to ASP.NET 5 course on Microsoft Virtual Academy. It covers a lot of good information including live.asp.net which is a production site used to for the ASP.NET 5 community stand up.