Home > C#, eID > Authenticating users with the Belgium eID in ASP.NET

Authenticating users with the Belgium eID in ASP.NET

Every Belgium resident has an eID card. This card functions as PKCS#11 keystore containing two X509 certificates (including their private keys): one for authentication and one for digital signing. These certificates are protected against a PIN/PUK code. The card can be used to authenticate the user in a web application using HTTPS with client certificate authentication. Because this mode of authentication makes use of two out of the three different types of information that can be used for authentication (something you know and something you have), it can be considered strong authentication.

In a classic HTTPS scenario, only the server will prove its identity to the user by making use of its X509 certificate, it is then up to the web application to do an authentication of the user in applicative code (over the secure SSL tunnel). With client certificate authentication, both the server and the user (in fact the browser) will prove their identity by making use of their X509 certificate.

eID authentication in ASP.NET

Authentication based on the Belgium eID card can be easily integrated into an ASP.NET web application. I have created the necessary code as an OWIN middleware component that can hooked into your web application and that will create a ClaimsIdentity representing the user. You can already find the source at Github (https://github.com/pieterderycke/Eid.Owin), but in the comming days I will also create a NuGet package for it.

The first thing you must do, is configure your web application to allow or require client certificates in IIS.

2015-08-04 19_54_32-Internet Information Services (IIS) Manager

2015-08-04 19_57_36-Internet Information Services (IIS) Manager

Once this is done, we can read out the client certificate in our OWIN middleware. There are a number of properties that can be parsed from the certificate. My code will create claims for all these properties

public class EidAuthenticationHandler : AuthenticationHandler
{
    protected override async Task AuthenticateCoreAsync()
    {
        var x509 = Context.Get("ssl.ClientCertificate");

        if (x509 != null)
        {
            ClaimsIdentity identity = ValidateX509Certificate(x509);
            return new AuthenticationTicket(identity, new AuthenticationProperties());
        }
        else
        {
            return new AuthenticationTicket(null, new AuthenticationProperties());
        }
    }

    private ClaimsIdentity ValidateX509Certificate(X509Certificate2 x509)
    {
        var chain = new X509Chain(true);
        chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline;
        chain.Build(x509);

        X509Certificate2 citizenCertificate = chain.ChainElements[0].Certificate;

        if (citizenCertificate.NotAfter  DateTime.Now)
            throw new Exception("The citizen certificate is not (longer) valid.");

        //TODO verify if citizen certificate has not been revoked

        if (chain.ChainElements[1].Certificate.Thumbprint != "74CC6E5559FFD7C2DD0526C0C21593C56C9384F3")
            throw new Exception("Invalid Citizen CA certificate.");

        if (chain.ChainElements[2].Certificate.Thumbprint != "51CCA0710AF7733D34ACDC1945099F435C7FC59F")
            throw new Exception("Invalid Belgium Root CA certificate.");

        string firstName = Regex.Match(citizenCertificate.Subject, "G=([^,]*),").Groups[1].Value;
        string lastName = Regex.Match(citizenCertificate.Subject, "SN=([^,]*),").Groups[1].Value;
        string nationalRegisterIdentificationNumber = Regex.Match(citizenCertificate.Subject, "SERIALNUMBER=([^,]*),").Groups[1].Value;
        string nationality = Regex.Match(citizenCertificate.Subject, "C=([^,]*)").Groups[1].Value;

        // Based on information of: https://www.ksz-bcss.fgov.be/nl/bcss/page/content/websites/belgium/services/docutheque/technical_faq/faq_5.html
        bool isMale = int.Parse(nationalRegisterIdentificationNumber.Substring(6, 3)) % 2 == 1;

        ClaimsIdentity identity = new ClaimsIdentity(Options.SignInAsAuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, firstName + " " + lastName, null, Options.AuthenticationType));
        identity.AddClaim(new Claim(ClaimTypes.GivenName, firstName));
        identity.AddClaim(new Claim(ClaimTypes.Name, lastName));
        identity.AddClaim(new Claim(ClaimTypes.Gender, isMale ? "M" : "F"));
        identity.AddClaim(new Claim(ClaimTypes.Country, nationality));

        return identity;
    }
}

And for average Joe programer, this is super easy. All he/she has to add to his "Startup.Auth.cs" file is the following code and he/she can authenticate the users based on the eID card.

app.UseEidAuthentication(new EidAuthenticationOptions() 
{
	SignInAsAuthenticationType = "Cookies"
});
Advertisements
Categories: C#, eID
  1. October 18, 2015 at 20:58

    Hey Pieter,

    I want to build a asp.net website and was wondering how you can retrieve the date of birth when the page loads.

    • pieterderycke
      October 19, 2015 at 07:27

      Hello Frederik,

      You could modify the code to extract the date of birth out of the “rijksregister nummer”/nationalRegisterIdentificationNumber.

      • October 19, 2015 at 10:04

        Thanks, nice work by the way.

  2. Kevin
    December 11, 2015 at 10:22

    is there a posibility to also get the address, I don’t see it in the current data

  3. Kevin
    December 11, 2015 at 10:24

    Hello Pieter,

    Is there also a posibility to get the adress information?

    Kind regards,

    Kevin Tahon

  4. pieterderycke
    December 12, 2015 at 20:16

    Hello Kevin,

    The address information is to my knowledge not in the X509 certificate. But you could read it with the Java applet (have a look at https://github.com/e-Contract/eid-applet)

    Kind regards,
    Pieter

  5. March 2, 2016 at 15:30

    Hi Pieter, thanks for the useful info. I’m looking for a solution to read eID address info as you mention in the previous post. I need to read eID info to fillout some input fields on a registration page in my .NET webapplication but not sure how to proceed. I use C#.

    Thank you and kind regards

    Dominique Hermans
    https://be.linkedin.com/in/dominiquehermans

  6. Maarten
    March 8, 2016 at 16:22

    Hello Pieter,

    I have downloaded your code sample and build it, but I only get the ‘Anonymous’ text.
    Is there anything else required to test it on my local machine? Do I perhaps need to configure/install other software to make it work?

  7. Maarten
    March 8, 2016 at 16:38

    Hello Pieter,

    I have tried your example and all I got is the ‘Anonymous’ response. Is there anything else which I need to configure to make this work?

  8. Maarten
    March 8, 2016 at 16:38

    Ignore my previous comment. Apparently it does not show directly on the page. My first comment was the proper (and most detailed) question.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: