Configure preview features with Azure App Configuration

In my preview post about implementing preview features in asp.net core, I explained how to introduce the concept of feature flags in your application and manage it with the default appsettings.json.

Managing your features from appsettings is not the best approach as it requires application restarts which will distrupt the application users.

In this post, I will explain how to do the configuration with a tool that was built just for this.

Azure App Configuration has feature management feature that allows you to manage your features, turn it on or off and set the filters for each feature flag. It also enables auto refresh which basically allows you to change a feature and this change will reflect immediately in your application.

Register Azure App Configuration as a Configuration Source

Asp.net core supports multiple configuration sources. When you call the CreateDefaultBuilder method in Program.cs, it automatically registers the following configuration sources for your application

appsettings.json
appsettings.{environment}.json
user secrets
environment variables
command line arguments

The registration happens in the same order above. You can have a look at the source code in this link If a specific key exists in a configuration source, you can override its value by adding it in the next configuration source. Ex: If the key ConnectionStrings:DefaultConnection exist in appsettins.json and also exist in user secrets, the one in user secrets will be used. This is good to override some values in your local dev environment such as passwords and connection strings to avoid pushing it to your source control

To register azure app config as an additional config source, you can add the following in Program.cs after installing the package Microsoft.Azure.AppConfiguration.AspNetCore

            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration(config =>
                {
                    var configuration = config.Build();
                    config.AddAzureAppConfiguration(azureAppConfig =>
                    {
                        var azureAppConfigConnectionString = configuration["AzureAppConfig:ConnectionString"];
                        azureAppConfig.ConfigureRefresh(refresh =>
                        {
                            refresh.SetCacheExpiration(TimeSpan.FromSeconds(5));
                        });
                        azureAppConfig.UseFeatureFlags();
                        azureAppConfig.Connect(azureAppConfigConnectionString);
                    });
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

From line 2-15, you can see that we are configuration the application configuration by adding a new configuration source in line 5. In line 7, we are reading the connection string from the previous configuration sources. This way you can add your connection string in appsettings.json or user secrets, I have added it here in appsettings.json under the name AzureAppConfig:ConnectionString. From line 8-11, we are configuring the caching time for the configuration. If you configure it for 5 seconds, the keys from azure app config will be cached and no requests will be done to azure app config to get the latest updates. Line 12 simply asks Azure App Configuration SDK to include the features when it reads all configurations and finally we use the connection string to connect to the azure config instance.

Creating Azure App Config

Log in to Azure Portal and create a new App Configuration resource. You can only create one free app configuration per subscription. Once it is created, go to Access Keys from the left menu and copy either the primary or secondary connection string and update your appsettings file

Now you should be all set. If you run the application and navigate to https://localhost:44375/PreviewFeatures, you should be able to see the page if your feature configuration allows it.

So far, we didn’t add any features to our Azure App Config instance yet, this means the application will fall back to the appsettings.json

Add Features in Azure App Configuration

To start managing your features from Azure App Config, Click Feature Manager from the left menu and Choose Add then type the feature name as PreviewFeatures and choose Off then click add

Now refresh the URL https://localhost:44375/PreviewFeatures, and if the feature PreviewFeatures was enabled in appsettings, it will still appear. So what are we doing wrong?

Enable Auto Refresh

By default, the Azure App Configuration does not do auto refresh in your asp.net core. You have to register a middleware that does that by adding the following line in the Configure method inside Startup.cs

app.UseAzureAppConfiguration();

Now, if you run the application again, the first time it starts, it will get the most recent values from Azure App Config and now you should see the PreviewFeatures controller not working. But if you enabled it again from azure portal by toggling the On/Off flag from the Feature Manager page, and wait for 5 seconds, you should refresh and see that the PreviewFeatures is now working again.

Notice that the toggle turns on or off the feature for everyone. If you need to use the feature filter, then click the 3 dots and choose Edit. Under Filters, click add and type the feature filter name, in this case UserFeatures which we created previously. Notice how the state changed from On/Off to Conditional. Now when you refresh, the filter will be executed to decide if the feature should be enabled or disabled for each user.

I have included all the updates on GitHub repo. Feel free to ask me any questions

Migrate your asp.net settings to Azure App Configuration

Before asp.net core, we only had the web.config file to configure and read the application settings from code. The framework didn’t have a plugable way of adding an extra configuration providers. Any other confiruation data sources meant a custom solution and custom code to read and update configuration keys.

With asp.net core, we got the new appsettings.json as one source of configuration. Along with it came the environment variables, other files, secret keys that can be used to omit connection strings and passwords from being stored on source control.

Things event got better with Azure App Service that has a settings/configuration section that can override the application settings and connection strings sections. This applies to both asp.net framework and asp.net core.

Isn’t this enough already?

It is good as a start. but, it has a major issue. If you change any value in your configuration keys, it means the application must be restarted which affects the logged in users and may cause data loss.
Another issue is that our application code and configuration exists in the same place which contradicts with the twelve factor . These configuration keys cannot also be shared with other applications except using copy/paste

Azure App Configuration

Azure App Configuration is a service that is still in preview that can be a central place for all your configuration keys and feature flags.
It is so easy to add it to your asp.net core configuration provider using the provided nuget packages.

Add the need packages

First, install the package Microsoft.Azure.AppConfiguration.AspNetCore . You may need to check that you enabled prerelease versions if you are using visual studio

In your Program.cs file, add the following code which will inject Azure app configuration as a configuration provider. Notice that you will have to add a key named “AppConfig” in your connectionStrings section in appsettings.json that will store the connection string for your Azure App Configuration

public static IWebHostBuilder CreateWebHostBuilder(string&#091;] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            var settings = config.Build();
            config.AddAzureAppConfiguration(settings&#091;"ConnectionStrings:AppConfig"]);
        })
        .UseStartup<Startup>();

Now, your application is ready to read any configuration keys from Azure App Configuration. All you need to do is to create a new instance by following this link

Reuse your existing configuration keys

It’s not only too easy to add Azure App Configuration to your asp.net core app but also migrating your existing keys. You don’t want to end up with a situation where you have to spend hours moving your keys manually or writing scripts to do it. Azure App Configuration can do that for you.

As you can see above, it is too simple. Just choose Import/export from the left menu then choose where you want App Configuration to import the values from:

  1. App Configuration: you can import the values from another Azure App Configuration instance
  2. App Service: which can be perfect in our case since it will import the values from your Azure App Service
  3. Configuration File: you can pass the appsettings.json directly and it will import the values from there

Once you did that, you will have all keys/connection strings imported and ready to go.

Conclusion

Azure App Configuration is a great service that still in preview but it enables you to offload your application from configuration keys and connection strings. It also has the auto refresh which will allow your app to always have the latest config keys without the need to restart your application and impact your users.
It also has feature management which is a great addition but we will talk about it in future posts.

Web API with windows authentication on asp.net Core 2

Most REST services that are being built using asp.net core now are using token based authentication either using asp.net core authentication middleware or third party products such as Identity Server. But, sometimes you only need to build your APIs for intrenal use within your organization who happens to be using Windows Authentication.

In this point, I will explain how to build a web API that utilizes AD for authentication and AD groups for authorization and how to integrate it with authorization policies.

Creating the project

Open Visual Studio 2017, Create new asp.net core Web Application and name it AspnetCoreWindowsAuth, then press Ok. Choose Web API as a project Template and Change the authentication method to Windows then press Ok to create the project.

If you select the project in the solution explorer and press F4, you will find nothing to set the authentication mode to Windows and enable/disable anonmous access just like you used to do in normal MVC web application. This is because it is moved to the launchsettings.json file under the properties folder. If you want to change it, you have to open the file and edit the value of the json property iisSettings which looks like below:

IIS SettingsYou can also modify the URL and SSL settings.

Now, if you run the project, it will run just fine and you can call the default Values controller and see the output and even windows authentication will be working as well and you can get the name of the logged in user using the User.Identity.Name property and it will return the Domain\\username although we didn’t add any authentication code yet in the pipeline

Add windows authentication middleware

Now, lets add the authentication middleware into the request processing pipeline. Add the line  app.UseAuthentication(); in the Configure method just before the  app.UseMvc(); . Remeber that the middlewares run in the same order they were added in the Configure method.

Add the following code in the ConfigureServices method before the services.AddMvc();

services.Configure(options =>
{
options.AutomaticAuthentication = true;
});

services.AddAuthentication(IISDefaults.AuthenticationScheme);

To make sure this is working fine, you can edit the Authorize attribute on the ValuesController and add the role name which should be an AD group name, ex: Employees

[Authorize(Roles ="Employees")]

Now you have asp.net core working fine with Active Directory and you can can authenticate the users according to the AD groups they belong to.

Using Authorization Policies

If you need more fine grained control over your controllers and you need to add more authorizastion logc, then you can go for authorization policies and it is really easy to configure as you can see below. Just add the following lines in the ConfigureServices method before the AddMvc statement

services.AddAuthorization(options =>
{
options.AddPolicy("OnlyEmployees", policy =>
{
policy.AddAuthenticationSchemes(IISDefaults.AuthenticationScheme);
policy.RequireRole(""S-1-5-4");
});
});

Here we defined a policy called OnlyEmployees and it requires the users to be windows authenticated and in the Role named Employees which is eventually mapped to AD group named employees. Notice that I didn’t write the name Employees in the RequireRole method. Instead, the value “S-15-4” was used, which is the SID for the AD Group named Employees. I found that this is how the group names are mapped to Roles in asp.net core and even if you tried to retrive the list of claims that the user have, it will translate to all SIDs of the groups that the user belongs to in AD.

To utilize this policy you have to annotate the controller or method with it as below

[Authorize(Policy = "OnlyEmployees")]
[Route("api/[controller]")]
public class ValuesController : Controller
{

}

By now you should have a working solution that depends on windows authentication and AD groups. Notice that this will only work with windows and most probably IIS.

You can find the code on GitHub if you want to use it or add to it.

https://github.com/haitham-shaddad/aspnetcore-windows-auth

MVC 5 – OWIN and Katana

OWIN was the first step towards elegant design for the whole asp.net stack. By separating the hosting concerns from the framework, Microsoft was able to build modular services and add it to the stack such as Web API, SignalR and now the whole asp.net core.

Katana was the first implementation for OWIN on IIS, you won’t feel much change as it is still running using the System.Web assembly but at least it enables you to run your middlware under IIS.

To understand more about the motivation, the moving parts and samples of OWIN, you can watch the following video in Arabic.

 

 

Security Options for Asp.Net (Arabic)

This is a series of videos to explain the available options to secure your asp.net application. Although the demonstration is done using MS Stack, it applies to any technology.

In each video, we will take an authentication type, explain its concept and show a demo on an asp.net application. we should cover the following authentication types

  1. Basic
  2. Digest
  3. Windows
  4. Certificate
  5. Forms
  6. Claims
  7. OAuth

 

Here is the link to the YouTube playlist, I will add each video once it is recorded. Feel free to leave any comments or suggestions

Tips and tricks to enhance asp.net security

There are many ways to enhance Asp.Net Web Application security, either on the web, back-end or database level, in this post, I will list some useful tips and tricks that will help you make your web application more secure.

Although the article discusses the concerns in asp.net context, it is applicable to any other framework

Web Level

Connection String

There are 2 ways to configure the security for your database connection in connection string. The first one is  windows authentication, your application connect to the database server using the Application Pool Identity, and this is the recommended way as it doesn’t include writing any User Passwords in your connection string, not to mention the need to edit web.config with the new password if it has expired, which will cause a restart in the IIS application pool.

The second way is to connect through SQL authentication, in this case, you should not have the password added as a plain text, you must secure your connection string by encrypting it, .Net already support this by running the following command

aspnet_regiis -pe “connectionStrings” -app “/MyCustomApplication”

The aspnet_regiis exe can be found in your Microsoft.net folder under C:\Windows\Microsoft.net, you should find a folder with the version of your framework, ex: v2.0.*

the -pe parameter specifies which section of your web.config you want to encrypt and the -app parameter specifies which IIS web site you want to use.

The algorithm used to encrypt is RSA, for more information about how does this work, please refer to https://msdn.microsoft.com/en-us/library/dtkwfdky.aspx?f=255&MSPPError=-2147217396

Service Accounts Privillages

The service account is used to run the application pool which in turn run the web application, and it is the account that you web application uses as identity when it needs to connect to the database if you specified Integrated Security=True or if you need to have an access to file system, for ex: Logging.

This account must have the least privilege, on the file system, only give it a read access to a specific folder if this is all what you need, on the database, don’t just get lazy and give it db_owner, only grant it the permissions it needs, if it only needs read or write on certain tables, then let it be and don’t give it access to everything.

Why is that? because simply, if someone succeeded to get to this service account, they could harm your servers, I have seen many cases where people uses a domain admin as a service account, imaging what a hacker could do with such account.

Cross Site Scripting (XSS)

Imagine you have a web application, and there is the page with the URL: http://somesite/dashboard/pay?amount=1000.

This page is requested using GET and it needs the user to be authenticated, now the user can only access if he is logged in, but think of the following scenario:

You access a site named: http://someothersite, and in this site, there is an image with a src =http://somesite/dashboard/pay?amount=1000&toAccount=123-123-123.

What will happen is that your browser will automatically try to fetch the source of the image and make a get request to the URL, and by design, the browser will automatically send the cookies for somesite domain including the authentication cookie, and the result will be the execution of the URL and pay the amount of 1000 because the request seems legitimate.

To prevent this issue, you must implement something called Anti-Forgery tokens, this simply means that with each request, the site will put a hidden field in the page and store its value in the user session or cookie, and when the user posts the page to the server, the server will validate that the value in the hidden field is equal to the value stored in the session or cookie, then it will clear the value in the session, this way, if the user tried to submit the page again or in our example, another site request the URL on behalf of the user, the server will deny the request because the request will not include the correct value for the anti-forgery token.

MVC has an excellent support for this by calling the @Html.AntiForgeryToken() in the view and annotating the action method by [ValidateAntriForgery] attribute

to read more about it, follow these links Anti-Forgery in asp.net , Anti-Forgery in web API

SQL Injection

Although this is a very old issue and nearly most of the existing ORM solutions handle it, still some people fall into this problem, the danger of this issue, is that the hacker can get to your database, your database server and from there, he can get to all your other servers, so always validate the user input, always use parameterized queries and skip the user strings if you are building a dynamic SQL.

Web.Config Encryption

Same issue as the connection string, but applies also to keys stored in app.config, you can also call the same command and encrypt the appsettings section, you don’t need to worry about the decryption cause .Net makes it automatically for you

HTTPS

If your application has sensitive data and you want to prevent any chance of the network between the user and the web server being spoofed, then enable HTTPS, it works by encrypting the traffic between the browser and the server by a public/private key using certificate.

Cookies

If your site is using cookies for authentication or maintaining client state, then make sure no sensitive data is there, also if you don’t need to access the cookie inside your client browser, then mark the cookie as Http Only, if the cookie has httponly enabled then it will not be accessible through JavaScript and the document.cookie JavaScript object will not contain this cookie.

Another trick is to mark your cookie as secure only, this will make it accessible and the client will send it to the server only if HTTPS was enabled on the web site, this will ensure that your cookie is safe

Files under virtual directory

Don’t leave any backups in your virtual directory, sometimes we make a backup from web.config in the shape of web.bak or some other format, these files may be served to the client and a hacker can use the info inside it to hack your application.

Session Hijacking

If you are using session variables, which is mainly some variables stored on server session or a state server, depending on your configuration, the web server has to has a key for your session in order to be able to retrieve the data for your session, this key is called Session ID, and by default it is stored in a cookie named ASP.NET_SessionId, if someone gets to this cookie value, they will be able to log in to the site, use any cookie editor extension and update the session ID to your ID and from there they will be logged in as you, so if your site has an edit profile page or a page that allows the user to add credit card info, this data will be stolen.

To prevent session hijacking, you have to do the following:

  1. Use SSL, this way no one will be able to capture the traffic between your users and the web application, consequently, they won’t capture the session ID cookie value
  2. Make the session ID value harder to guess, the worst thing to do is to make the session ID as incremental value, if I logged in and found my session ID as 12345, then I can easily edit it to another number and it will be easy to obtain the session for another user
  3. Set the session ID cookie to be always Http Only, this will prevent any JavaScript from reading its value and will make it harder for any XSS
  4. Regenerate the session ID, this will make it harder for the attacker, even if he got the session ID, it won’t be valid for long time
  5. Prevent concurrent sessions, if you have your user logged in from one session, and he tried to login from another session, there is a probability that he is not the same person, you can be more certain by validating the IP and time used, ex: if the user IP is from USA, and at the same time the user is trying to connect from Europe, then most probably this is an attack

Eliminate unneeded headers

Some headers are not necessary in your web page response, such as Server, Asp-Net version and so on, these headers not only add a performance headache, but make the attacker job easier as he already knows what framework, servers and environment he will be attacking, so always edit your web.config or IIS Console and remove these unneeded headers

Database Level

Data Encryption

A very simple case for encrypting the data is the user passwords, never store it in plain text, you have to use a strong algorithm to encrypt the important data in your database, but note that this will affect the performance of the application because the web application will have to do some calculations to encrypt the data before persistence and decrypt it after retrieval, also you will not be able to write queries that include any of the encrypted columns.

SQL Server 2016 has a great feature called Dynamic Data Masking, it allows you to mask the data stored in a column in some predefined formats, ex: Credit Card, Social Security Number or an email address, permissions can be granted for some users and only those users will be able to see the data unmasked.

To read more about the topic, please follow this link

IPSec

This feature blocks all incoming connections to a specific server on all ports and allows you to allow certain IP and certain port, so in this case, the database server will not allow any connections but from the web servers for your application

IPsec Configuration

SQL Server Transparent Data Encryption (TDE)

In case all the above precautions failed to protect your database, at least you can protect the data on rest, TDE allows you to encrypt the database’s data file itself so that no one can open it on another computer without a secret key, to encrypt your database file, you need a master key, certificate protected by this master key, a database encryption key which is protected by the certificate and finally set the database to use encryption.

To read more about it, following this link https://msdn.microsoft.com/en-us/library/bb934049.aspx