Skip to content

Introducing Thinktecture IdentityManager

April 9, 2014

Back in 2005 when Microsoft released the ASP.NET MembershipProvider API, they also included in Visual Studio the ASP.NET WebSite Administration tool. This was used by developers to quickly create and edit users to populate the MembershipProvider database. Given Microsoft’s move away from Membership, this tool was removed from Visual Studio and many developers have missed it. In a similar vein, ever since I built MembershipReboot I’ve been meaning to provide an admin tool to allow similar functionality that was in the ASP.NET WebSite Administration tool.

Well, I finally got around to building said tool — introducing Thinktecture IdentityManager.

IdentityManager is developed as OWIN middleware and can easily be hosted in any OWIN host. Also given the recent release and popularity of ASP.NET Identity, I designed it to support both MembershipReboot and ASP.NET Identity.

It’s very early in its development, but this first preview version is intended to allow developers or administrators to create users, change password, email, phone and claims. Also, you can query the entire database and filter for the user’s user name or name claim (display name). I plan to also add role management support and more self-service identity management features. Also, I will be working on a strategy for securing IdentityManager so it can be used in scenarios beyond just development.

Below are some screen shots.

Home page:

idmgr1

Searching/browsing users: idmgr2

Editing a user:

idmgr3

The code that’s needed to host IdentityManager looks something like this:

public void Configuration(IAppBuilder app)
{
    app.UseIdentityManager(new IdentityManagerConfiguration()
    {
        UserManagerFactory = Thinktecture.IdentityManager.MembershipReboot.UserManagerFactory.Create
    });
}

As you can tell, it’s fairly simple in terms of the current features and the setup. I’ll write another post with more details on customizing the configuration of the identity libraries. In the meantime, the code for IdentityManager is open source and available on github.

There is also a short video showing the features and configuration.

Feedback welcome via the github issue tracker.

 

How I made EF work more like an object database

March 30, 2014

I’m not a DB guru, so EF is usually very helpful for me. I like EF’s ORM capabilities, as this is quite a natural desire to want to map a set of in-memory objects to a database. This is all good, except when EF is a relational snob and I am an ignorant object-oriented programmer. The issue I refer to is that of “child orphans” in EF/DB speak.

The setup is this: I have a parent table/entity (let’s call it Person) and I have a child table/entity (let’s call it Pet). In my object oriented mindset a pet only exists in the context of a person – in other words you have to have a parent person object to have a pet (I don’t do strays a la Sochi).

public class Person
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual ICollection<Pet> Pets { get; set; }
}

public class Pet
{
    public virtual int ID { get; set; }
    public virtual int PersonID { get; set; }
    public virtual string Name { get; set; }
}

And as you can tell from my object model, I didn’t want to fall into the normal EF code first style where child entities had navigation properties to their containing entity – that feels wrong to me (but I understand the need for a foreign key once mapped to the DB, thus the PersonID).

Anyway, to map this to the database I have a DbContext with a DbSet<Person>. I override OnModelCreating to overcome my lack of the navigation property I mentioned above:

public class PersonDatabase : DbContext
{
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>().HasKey(x => x.ID);
        modelBuilder.Entity<Pet>().HasKey(x=>x.ID);
        modelBuilder.Entity<Person>().HasMany(x => x.Pets)
            .WithRequired().HasForeignKey(x => x.PersonID).WillCascadeOnDelete();
    }
}

And here’s an example of inserting into both tables:

using (var db = new PersonDatabase())
{
    var brock = db.People.Create();
    brock.Name = "Brock";
    var dog = new Pet();
    dog.Name = "Roo";
    brock.Pets.Add(dog);

    db.People.Add(brock);
    db.SaveChanges();
}

So notice no DbSet<Pet> is needed with EF in the DbContext. EF recognizes the relationship and will happily map any Pet in the Pets collection to a Pet table. I find this quite nice of EF and it plays right into my OO mindset. So naturally (or so I assumed) I thought I could remove a Pet from the collection of a Person and the Pet would be deleted from the table:

using (var db = new PersonDatabase())
{
    var brock = db.People.Single(x => x.Name == "brock");
    var roo = brock.Pets.Single(x => x.Name == "Roo");
    brock.Pets.Remove(roo);
    db.SaveChanges();
}

Not so. You get the exception:

Unhandled Exception: System.InvalidOperationException: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

It turns out that EF stops being about object relational mapping and decides to be a relational snob at this point. I am happy conceding that it’s right and knows more than me, but I just want my child row to be deleted. I don’t want to change my object model to support null FKs (since that’s not a correct mapping of my model). Also I’m quite confused because EF was kind enough to discern the Pets collection in Person it knew to automatically create the Pet table and inset rows when I added them to Person, but it doesn’t know to delete them when I remove them from the Person (especially when the foreign key is not null – I did that on purpose!). So I have a slight complaint that the behavior for adding doesn’t parallel the behavior for removing. Anyway, it knows best (I guess).

Turns out this behavior is nothing new and here’s the explanation: http://blog.oneunicorn.com/2012/06/02/deleting-orphans-with-entity-framework/

I was unsatisfied with this solution as it didn’t allow me to maintain my OO mindset when it came to EF (recall: it’s an object relational mapper). To solve my problem, I needed to be even more explicit (or deliberate) and use some interesting hooks in EF to tell it what I wanted it to do. It turns out there are enough events to let you know when an item is being removed from a collection, and in those event handlers you can mark and item as being removed to get the delete semantics I was looking for.

Here’s the insane code:

public class PersonDatabase : DbContext
{
    public PersonDatabase()
    {
        this.Set<Person>().Local.CollectionChanged +=
            delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    foreach (Person person in e.NewItems)
                    {
                        var entities = person.Pets as EntityCollection<Pet>;
                        if (entities != null)
                        {
                            entities.AssociationChanged += 
                                delegate(object sender2, CollectionChangeEventArgs e2)
                                {
                                    if (e2.Action == CollectionChangeAction.Remove)
                                    {
                                        var entity = e2.Element as Pet;
                                        if (entity != null)
                                        {
                                            this.Entry<Pet>(entity).State = EntityState.Deleted;
                                        }
                                    }
                                };
                        }
                    }
                }
            };
    }
}

So I read this as: any time a Person is materialized into the DbContext (either via inserting or loading) wire up to the Pets collection foreign key events. If that foreign key event is to remove the foreign key, then I want to remove the entity from the DB (which is the Pet). This gives me my OO semantics in a relational world. Too bad this isn’t easier in EF.

HTH

LIDNUG — Katana Authentication Middleware

March 20, 2014

Slides and demos from my recent LIDNUG session on Katana Authentication Middleware are here:

http://1drv.ms/1eq5zQk

Recording is here:

TBD

During my presentation I ran into an issue where my external provider cookie wasn’t being issued. In retrospect this was a noob mistake, but what had happened was that the google authentication middleware was registered prior to the cookie middleware in the Katana pipeline. The google middleware was trying to issue the cookie the cookie middleware had not yet be activated in the pipeline, and thus wasn’t issuing being invoked to issue the cookie. Sorry — I should have known better, but it makes for a good learning point!

Thanks.

Demos — VS Live/Web Dev Live Las Vegas 2014

March 15, 2014

Here are the slides and demos from my sessions at VS Live in Vegas.

Thanks to everyone that attended, and thanks to the organizers at VS Live for having me.

LIDNUG — Intro to OWIN and Katana

February 28, 2014

Here are the slides and demos from my talk on OWIN and Katana at the LIDNUG:

http://1drv.ms/1cfsjnG

Also, here’s the talk itself:

https://www.youtube.com/watch?v=DRPVO3-W4Rs&feature=c4-overview&list=UU-DCjVla8pR4tbHpen8dUsQ

Thanks.

Introducing IdentityReboot

February 11, 2014

I’ve been a vocal critic of the Microsoft identity solutions. In their defense this is not a trivial subject, but I feel that they’ve not really spent the time or focus they need to to provide a fully robust solution given the putative standards for modern security. ASP.NET Identity v2 is the latest iteration in the history of their implementations, and while it’s the best so far I feel there are still major issues with the security of the implementation.

I’ve also been touting MembershipReboot as an alternative, but I have realized several issues related to its visibility and adoption. MembershipReboot is a fairly small open source project. It’s a completely different library than the one(s) from Microsoft. I’m the only main developer. I am not paid to work on it. I do not have a staff. I only have the barest of documentation (I know — shame on me). The only real support is via the github issue tracker. And perhaps most importantly it’s hard to gain notice amid the marketing behemoth that is Microsoft. Notice in this very recent video there is no mention of how passwords are stored or how their library actually provides any security; rather topics such as EF and Azure are discussed *rolls eyes*. So, I completely understand that many won’t consider or even notice MembershipReboot and will adopt ASP.NET Identity without knowing any better.

IdentityReboot

Despite this I’m still doing my best to make this space better. As such, I’m announcing IdentityReboot.

IdentityReboot is a set of extensions to ASP.NET Identity that implement the major missing features I’ve complained about (put up or shut up, right?). The code to do this is essentially the same code I have already implemented in MembershipReboot, but it’s been adapted to the ASP.NET Identity programming model. The master branch targets ASP.NET Identity v2, but there is a v1 branch for ASP.NET Identity v1.

The main features provided by IdentityReboot (targeting v2) are:

  • Per-account adaptive password hashing (as discussed here)
  • Login and two factor authentication code brute force prevention (as discussed here)
  • Fix the issue with the time-based two factor authentication codes (as discussed here)

The various components provided are:

AdaptivePasswordHasher

The password hashing algorithm is pluggable in ASP.NET Identity, so IdentityReboot provides an AdaptivePasswordHasher class that implements the password stretching I described here.

The AdaptivePasswordHasher constructor allows a developer to indicate the number of iterations to use. If the iterations are not provided then it uses the year-based adaptive algorithm. It can then be configured on the UserManager.PasswordHasher property and it will be used when password hashing is needed by the UserManager.

The iteration count is stored in the hashed password string itself so there’s no schema change needed. Also the AdaptivePasswordHasher is compatible with passwords already hashed and persisted with the built-in password hasher from ASP.NET Identity. This means you can add this and your existing users hashed passwords will still work.

IdentityRebootUserManager

To implement brute force prevention for passwords and two factor codes, the logic from the ASP.NET Identity UserManager had to be replaced. To do this, IdentityReboot provides a UserManager-derived class called IdentityRebootUserManager.

IdentityRebootUserManager overrides the methods that perform password and two factor authentication code validation. If too many invalid attempts have been made within a window of time, then these validation methods fail not allowing the user to proceed. These values are configurable, but default to 5 attempts within 5 minutes.

To implement this brute force prevention, some data needs to be stored in the database. As such, a new store interface was introduced to persist the necessary data: IBruteForcePreventionStore. This interface models storage for the last date/time of the failed login and the number of failed attempts. This store interface pattern is consistent with ASP.NET Identity’s pattern to allow any storage implementation.

Also, by default, the IdentityRebootUserManager automatically configures and uses the AdaptivePasswordHasher mentioned above.

MobileStoredTwoFactorCodeProvider

To fix the issue with time-based two factor authentication codes, IdentityReboot provides a new token provider class called MobileStoredTwoFactorCodeProvider. This token provider is meant to replace those built-in with ASP.NET Identity and improves upon the time-based providers by generating a code that is valid for a window of time from the time it is generated (as opposed to fixed windows of time, as I describe here).

To achieve this, the MobileStoredTwoFactorCodeProvider creates a random code which is sent via SMS to the user. This code is also hashed and stored in the database along with the time the code was generated. The hash is necessary to thwart attackers that have access to the database. The time is used to ensure the user has a sufficient window in which to validate the token. The number of digits and the validity duration are both configurable, and default to 6 digits and a 5 minute window.

To store the pertinent data for the MobileStoredTwoFactorCodeProvider another new store interface was defined: ITwoFactorCodeStore. It models persisting the hashed two factor authentication code and the date/time it was issued.

IdentityReboot.Ef

Finally, there is also an IdentityReboot.Ef project that provides an EF-backed IdentityRebootUserStore that implements the two additional store interfaces and an IdentityRebootUser class which defines the properties needed for the new store interfaces.

Getting Started

To use IdentityReboot, you can either get started from the samples or you can create a new empty ASP.NET application and then add the “Microsoft ASP.NET Identity Samples” from the nightly builds (as documented here). There are also packages on NuGet here and here.

In your web project starting from the templates all that is needed is to reference the IdentityReboot assemblies and then make these changes:

  1. Change ApplicationUser to derive from IdentityRebootUser instead of IdentityUser (in ~/Models/IdentityModels.cs)
  2. Replace new UserStore with new IdentityRebootUserStore (2 locations in ~/App_Start/IdentityConfig.cs)
  3. Change ApplicationUserManager to derive from IdentityRebootUserManager instead of UserManager (in ~/App_Start/IdentityConfig.cs)
  4. Remove the two calls to RegisterTwoFactorProvider and replace them by registering the MobileStoredTwoFactorCodeProvider.

If you have an existing database then you will need to use EF migrations to update the database with the new schema for the new stored data.

The intent with IdentityReboot was to enhance the security of ASP.NET Identity with as few changes and disruptions as possible. Again, all of these are illustrated in the samples.

Feedback welcome.

Concerns with two factor authentication in ASP.NET Identity v2

February 11, 2014

I’ve been doing a bit of research into how ASP.NET Identity v2 is implementing its new features, specifically two factor authentication. I was curious, of course, because I’ve had the opportunity to implement the same feature in MembershipReboot.  It’s interesting to see the differences, and as you might have realized (due to this blog post) I have some concerns with the approach Microsoft has taken (which I list below).

Note that ASP.NET Identity v2 is not yet released and this post is based upon the publicly available nightly builds.

Brute force attacks on two factor authentication confirmations

I’ve already commented on this issue here, but I list it here for completeness.

Email used as a second factor for authentication

In the new sample template application for ASP.NET Identity, there are two different delivery mechanisms configured for two factor authentication — one via SMS to the user’s mobile phone (which is a very common and expected approach) and another via email to the user’s registered email account. Using email as an option for two factor authentication surprised me, since I always understood two factor authentication to mean that a user must present two factors from something you have (e.g. key), know (e.g. password), or are (e.g. biometrics). Using the user’s email as a second factor does not achieve two factor authentication (at least according to the strict definition) and if you think I’m splitting hairs, then let me instead illustrate an attack against the email as the second factor.

Imagine an attacker compromises the user’s email (perhaps difficult, but it still happens frequently). Once the attacker has done this, then of course they are in a position to intercept the email based two factor authentication token. But in addition, the user’s password is also essentially compromised because the attacker can issue a password reset which is confirmed via the user’s email (this also illustrates why an identity management system should support password reset secret questions and answers). So controlling the user’s email thwarts both password and two factor authentication code.

If the user’s mobile phone is used instead as the second factor, then even if the user’s email is compromised the attacker would also need to compromise the user’s mobile phone to gain access to the application. This is the point of two factor authentication — it requires more effort of the attacker. Using the email just doesn’t seem very strong to me. I’d suggest disabling the email based two factor authentication and just utilize the mobile phone delivery mechanism.

Time-based two factor authentication codes

For the two factor authentication codes, ASP.NET Identity uses RFC6238 to generate these values (it’s ok, I had to look it up as well). Basically the way this works is that a code can be determined based upon the clock time (given various inputs to seed the algorithm). A code will remain the same for some configurable duration (say for a 5 minute window of time). This window of time is based upon the server clock time and not the time the code was requested. So this means (for a 5 minute window) from 2pm to 2:05pm the code will be a consistent value, but as soon as the clock hits 2:05pm the code will be different but won’t change again until 2:10pm. It’s a clever idea and is similar to how those RSA key chain code generators work.

Update: Scott left a comment below with details about TOTP I wasn’t aware of. It seems that the algorithm allows for old codes up to a certain threshold and it looks like ASP.NET Identity allows for 90 seconds. This means that the usability window for code is much more user friendly than I realized. This allays my concern with this aspect of the two factor auth codes and ASP.NET Identity, but I still feel the next issue is a problem (see below). My apologies to ASP.NET Identity for my misunderstanding and mischaracterization of the TOTP implementation.

My complaint about this approach for two factor authentication codes is that the user doesn’t have any insight into when the window of time expires (whereas they do for the RSA key chain code generators). For example, a user logs into the application at 2:04pm and the code for that window of time is sent via SMS to their mobile device. This means that the user only has 1 minute from the time the server sends the SMS, to receive the SMS, unlock their phone, open their text messages and then enter the code into the web application to prove control of their phone. There will be a certain percentage of users (those those login closer to the end of the window of time) that will not be able to enter their code in time before it changes. And there’s no way for the user to understand that the code they’ve just entered is stale. Oh and the other issue is that the window of time that ASP.NET Identity uses isn’t as gracious as 5 minutes — rather it’s 30 seconds. That’s a very narrow window of time before the code expires.

Even if this window is expanded to 5 minutes (which is the expiration of the short-lived cookie as described here), that still means that on average 10% of users will be issued codes with less than 30 seconds to enter them. I can only imagine the questions on the ASP.NET forums asking why sometimes two factor codes work and why sometimes they don’t. Also, I could see how this might become an application support headache.

I can only surmise why this was done, but my guess is that ASP.NET Identity took this approach so they would not have to store anything in the database for the two factor authentication code. It’s a tradeoff, but unfortunately I think this is the wrong tradeoff since it makes the developer’s job easier at the expense of user friendliness.

Two factor authentication code generation and all your database are belong to us

So recall how we should be storing passwords — the premise is that an attacker has pwnd your database. This means anything in your database the attacker has. Well, it turns out that the “various inputs to seed the algorithm” that I mention above for the time-based two factor authentication code generation are all either well known constant values or plaintext values from the user’s record in the database. This means if the attacker has access to the user’s record in the database they can calculate the exact same two factor authentication code that ASP.NET Identity generates. This also doesn’t seem very strong to me.

I know there are better approaches (since I built at least one in MembershipReboot), but the tradeoff was that some storage was required in the server. I think that’s an acceptable tradeoff for better security.