IdentityServer3 v2.2

Yesterday we published v2.2 to nuget and github. You can see the release notes here.

Besides a couple of bug fixes and refinements – the big features are support for the introspection specification (rfc 7662) and the OpenID Connect HTTP-based logout specification.

The next post will give you some perspective on introspection and Brock will write up the new features around logout. stay tuned!

PS. Brock and I will be at NDC London in January. If you are interested in identity & access control with Katana and ASP.NET (4&5) – join us!

Posted in .NET Security, ASP.NET, IdentityServer, Katana, OAuth, OpenID Connect, OWIN, Uncategorized, WebAPI | 5 Comments

IdentityServer3 Logging & Monitoring using Serilog and Seq

IdentityServer has two fundamental “monitoring” facilities : development-time logging and production-time eventing. The original docs are here.

Logging is for developers – in fact – when I start a new IdentityServer3 project, that’s the first thing I configure. For security reasons (and to be spec compliant) the error messages in IdentityServer are pretty vague – logging gives you a detailed inside view of what’s really going on.

We use the fabulous LibLog library for logging, which means we support logging frameworks like SeriLog, NLog, Log4Net and others out of the box. If you want to directly connect to a custom logging framework – we have a sample for that as well.

Depending on how much logging sources you enable, the logs will contain sensitive data like passwords, claims and tokens. This is where eventing comes in.

Events are more suitable for production scenarios where you want more high level – but also queryable – data. This includes typical events like login failed/success, errors etc… to connect IdentityServer to an event processing system (ELK being the most popular), you would implement the IEventService interface.

For this post I want to show you how to connect IdentityServer to Serilog for logging and a local Seq instance for querying and parsing events.

Logging
That’s super easy – first get Serilog from Nuget

install-package Serilog

If you are using an IIS hosted IdentityServer, you probably want to log to a text file using System.Diagnostics (here’s a nice tail tool to view those logs in real time). In that case, add the following Serilog setup to your Startup:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Trace()
    .CreateLogger();

..and add the following snippet to your web.config:

<system.diagnostics>
  <trace autoflush="true" indentsize="4">
    <listeners>
      <add name="myListener" 
            type="System.Diagnostics.TextWriterTraceListener" 
            initializeData="Trace.log" />
    </listeners>
  </trace>
</system.diagnostics>  

That’s it. LibLog will detect that Serilog has been configured in the host and will start piping all IdentityServer logging to it.

If you prefer self-hosts for IdentityServer (I do for dev time) – there’s a nice console log formatter:

install-package Serilog.Sinks.Literate

In that case add the following Serilog setup to your host:

Log.Logger = new LoggerConfiguration()
    .WriteTo
    .LiterateConsole(outputTemplate: "{Timestamp:HH:MM} [{Level}] ({Name:l}){NewLine} {Message}{NewLine}{Exception}")
    .CreateLogger();

This gives you nicely formatted console output

SerilogConsole

Eventing
Seq is free for single user, easy to use and easy to setup. To connect IdentityServer to Seq, I wrote the following event service:

class SeqEventService : IEventService
{
    static readonly ILogger Log;
 
    static SeqEventService()
    {
        Log = new LoggerConfiguration()
            .WriteTo.Seq("http://localhost:5341")
            .CreateLogger();
    }
 
    public Task RaiseAsync<T>(Event<T> evt)
    {
        Log.Information("{Id}: {Name} / {Category} ({EventType}), Context: {@context}, Details: {@details}",
            evt.Id,
            evt.Name,
            evt.Category,
            evt.EventType,
            evt.Context,
            evt.Details);
 
        return Task.FromResult(0);
    }
}

..and registered it like this:

factory.EventService = new Registration<IEventServiceSeqEventService>();

Using the Seq console, you can now query the events – e.g. for failed logons, IP addresses etc..

Seq

Nice! HTH.

(full source code can be found here)

Posted in .NET Security, ASP.NET, IdentityServer, OAuth, OpenID Connect, OWIN, WebAPI | 5 Comments

The State of Security in ASP.NET 5 and MVC 6: Authorization

The hardest part in designing an application is authorization. The requirements are always so app-specific that for 10 applications you often see 12 different implementations.

To make things worse, ASP.NET and MVC traditionally had not much more built-in to offer than boring role checks. This lead to either unmaintainable code (hard coded role names and Authorize attributes) or complete custom implementations – or both.

In ASP.NET 5, a brand new authorization API is supposed to improve that situation – and IMHO – oh yes it does. Let’s have a look.

Overview
ASP.NET 5 supports two styles of authorization out of the box – policy-based and resource-based.

Both styles are a substantial improvement over the current ASP.NET authorization features and reduce the need to write your own authorization attribute/filter/infrastructure – though this is still totally possible.

The new Authorize Attribute
My main gripe with the old attribute is that it pushes developers towards hard-coding roles (or even worse – names) into their controller code. It violates separation of concerns and leads to hard to maintain code with roles names sprinkled all over your code base.

Also – let’s face it – declarative, role-based security might be nice for demos but is nowhere near flexible enough to write  anything but trivial applications.

The new Authorize attribute can still do role checks like this:

[Authorize(Roles = "Sales")]
public IActionResult DoSalesyStuff()
{ /* .. */ }

But this is mainly for backwards compatibility (the ability to check for names is gone). The more recommended pattern is to use so called authorization policies instead:

[Authorize("SalesOnly")]
public IActionResult DoSalesyStuff()
{ /* .. */ }

Let’s have a look at policies next.

Policies & Requirements
Policies are a way to create re-usable authorization logic. Policies consist of one or more so called requirements. If all requirements of a policy are met, the authorization check is successful – otherwise it fails.

Policies are created using a policy builder, and the following snippet creates a very simple policy (aka “require authenticated users”) and sets that globally in MVC:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // only allow authenticated users
        var defaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
 
        services.AddMvc(setup =>
        {
            setup.Filters.Add(new AuthorizeFilter(defaultPolicy));
        });
    }
}

There are more extension methods similar to RequireAuthenticatedUser – e.g. RequireClaim or RequireRole.

Another common use case are named policies which can be referenced like the above SalesOnly example (again in Startup.ConfigureServices):

services.AddAuthorization(options =>
{
    // inline policies
    options.AddPolicy("SalesOnly", policy =>
    {
        policy.RequireClaim("department""sales");
    });
    options.AddPolicy("SalesSenior", policy =>
    {
        policy.RequireClaim("department""sales");
        policy.RequireClaim("status""senior");
    });
});

You can also encapsulate requirements in classes, e.g.:

public class StatusRequirement : AuthorizationHandler<StatusRequirement>, IAuthorizationRequirement
{
    private readonly string _status;
    private readonly string _department;
 
    public StatusRequirement(string department, string status, bool isSupervisorAllowed = true)
    {
        _department = department;
        _status = status;
    }
 
    protected override void Handle(AuthorizationContext context, StatusRequirement requirement)
    {
        if (context.User.IsInRole("supervisor"))
        {
            context.Succeed(requirement);
            return;
        }
 
        if (context.User.HasClaim("department", _department) &&
            context.User.HasClaim("status", _status))
        {
            context.Succeed(requirement);
        }
    }
}

Which can then be added like this:

options.AddPolicy("DevInterns", policy =>
{
    policy.AddRequirements(new StatusRequirement("development""intern"));
 
    // ..or using an extension method
    //policy.RequireStatus("development", "intern");
});

Under the covers, the AddAuthorization extension method also puts an IAuthorizationService (or more specifically the DefaultAuthorizationService) into the DI container. This class can be used to programmatically evaluate policies (amongst other things – more on that later).

To make the authorization service available – simply add it to e.g. a controller constructor:

public class TestController : Controller
{
    private readonly IAuthorizationService _authz;
 
    public TestController(IAuthorizationService authz)
    {
        _authz = authz;
    }
}

..and then use it in an action:

public async Task<IActionResult> SalesSeniorImperative()
{
    if (await _authz.AuthorizeAsync(User, "SalesSenior"))
    {
        return View("success");
    }
 
    return new ChallengeResult();
}

Scott used a slightly different approach, but using the same underlying infrastructure.

Remark ChallengeResult can be used to trigger an “access denied” condition in MVC. The cookie middleware e.g. will translate that either into a redirect to a login page for anonymous users, or a redirect to an access denied page for authenticated users.

Remark 2 Since views in MVC 6 also support DI, you can inject the authorization service there as well. Some people like this approach to conditionally render UI elements.

@{
    ViewData["Title"] = "Home Page";
    
    @using Microsoft.AspNet.Authorization
    @inject IAuthorizationService _authz
}
 
@if (await _authz.AuthorizeAsync(User, "SalesOnly"))
{
    <div>
        <a href="test/salesOnly">Sales only</a>
    </div>
}

This is a nice way to centralize authorization policies and re-use them throughout the application.

The only thing I don’t like about this approach is, that it pushes you towards using the claims collection as the sole data source for authorization decisions. As we all know, claims describe the identity of the user, and are not a general purpose dumping ground for all sorts of data – e.g. permissions.

It would be nice if one could use the DI system of ASP.NET to make further data source accessible in custom requirement. I’ve opened an issue for that – we’ll see what happens.

Resource-based Authorization
This is a new approach for ASP.NET and is inspired by the resource/action based approach that we had in WIF before (which was ultimately inspired by XACML). We also like that approach a lot, but the problem with the WIF implementation (and also ours) was always that due to the lack of strong typing, the implementation became messy quickly (or at least you needed a certain amount of discipline to keep it clean over multiple iterations).

The idea is simple – you identify resources that your application is dealing with – e.g. customers, orders, products (yawn). Then you write a so called handler for each of these resources where you express the authorization requirements in code.

You use requirements to express whatever action is supposed to be applied to the resource, and conclude with a success/failure, e.g.:

public class CustomerAuthorizationHandler : 
    AuthorizationHandler<OperationAuthorizationRequirementCustomer>
{
    protected override void Handle(AuthorizationContext context, 
        OperationAuthorizationRequirement requirement, 
        Customer resource)
    {
        // implement authorization policy for customer resource
    }
}

Operation requirements are built-in and can be used to model simple string-based actions – but you can also write your own, or derive from OperationAuthorizationRequirement.

public static class CustomerOperations
{
    public static OperationAuthorizationRequirement Manage = 
        new OperationAuthorizationRequirement { Name = "Manage" };
    public static OperationAuthorizationRequirement SendMail =
        new OperationAuthorizationRequirement { Name = "SendMail" };
 
    public static OperationAuthorizationRequirement GiveDiscount(int amount)
    {
        return new DiscountOperationAuthorizationRequirement
        {
            Name = "GiveDiscount",
            Amount = amount
        };
    }
}

You then register the resource handler with the DI system and can access it imperatively from within your controllers (using the above mentioned authorization service):

public async Task<IActionResult> Discount(int amount)
{
    var customer = new Customer
    {
        Name = "Acme Corp",
        Region = "south",
        Fortune500 = true
    };
 
    if (await _authz.AuthorizeAsync(User, customer, 
        CustomerOperations.GiveDiscount(amount)))
    {
        return View("success");
    }
            
    return new ChallengeResult();
}

What I like about this approach is that the authorization policy has full strong typed access to the domain object it implements authorization for, as well as the principal. This is a huge improvement over the WIF API. It also makes it easy to unit test your controller without the authorization code – and even more importantly (at least for security guy) – it allows unit testing the authorization policy itself.

protected override void Handle(AuthorizationContext context, 
    OperationAuthorizationRequirement requirement, 
    Customer resource)
{
    // user must be in sales
    if (!context.User.HasClaim("department""sales"))
    {
        context.Fail();
        return;
    }
 
    // ...and responsible for customer region
    if (!context.User.HasClaim("region", resource.Region))
    {
        context.Fail();
        return;
    }
 
    // if customer is fortune 500 - sales rep must be senior
    if (resource.Fortune500)
    {
        if (!context.User.HasClaim("status""senior"))
        {
            context.Fail();
            return;
        }
    }
 
    if (requirement.Name == "GiveDiscount")
    {
        HandleDiscountOperation(context, requirement, resource);
        return;
    }
 
    context.Succeed(requirement);
}

In addition, the resource handler can make full use of the DI system. That means we can inject access to arbitrary data stores. A very common use case is to use some sort of database to query permission tables or similar. This makes it very flexible.

Imagine a permission service that queries your authorization using some backing store (the _permissions variable):

private void HandleDiscountOperation(
    AuthorizationContext context, 
    OperationAuthorizationRequirement requirement, 
    Customer resource)
{
    var discountOperation = requirement as DiscountOperationAuthorizationRequirement;
    var salesRep = context.User.FindFirst("sub").Value;
 
    var result = _permissions.IsDiscountAllowed(
        salesRep,
        resource.Id,
        discountOperation.Amount);
 
    if (result)
    {
        context.Succeed(requirement);
    }
    else
    {
        context.Fail();
    }
}

All in all – I am very pleased with this new API and it will be interesting to see how it performs in a real application.

The full source code of the sample can be found here and the repo for the authorization API is here (open an issue if you have feedback)

Have fun!

Posted in .NET Security, ASP.NET, WebAPI | 15 Comments

Upcoming Identity & Access Control Workshops in Europe

Brock and I will be in London in November and January to hold our identity & access control workshop.

In November we are at the SDD Deep Dive event and do a very special three day version which includes extra content around IdentityServer3 and migrating to ASP.NET 5 and MVC6.

In January we will be at NDC London for a two day workshop which will also include the ASP.NET 5 content.

I will be also in Oslo in January to do the same two day version of the workshop.

Hope to see you at one of those events!

Posted in .NET Security, ASP.NET, IdentityServer, OAuth, OpenID Connect, WebAPI | Leave a comment

IdentityServer3 v2 Release and other Tidbits (aka what did I miss during Holidays)

I am back from my annual family/summer vacation. This time it was Norway, and it was excellent. Norway has stunning landscapes and excellent breweries – recommended!

During that time Brock released v2 of IdentityServer. This was a big release and incorporated a ton of feedback we got over the last year. Check the release notes because there are a couple of breaking changes.

Alongside we also made updates to the ASP.NET Identity and MembershipReboot support packages. We made the decision to turn them into source code packages that you can include into your projects and customize them to your hearts content.

The main driver for this decision was that many people used the 1.x binary releases as black boxes and never really bothered to understand was a user service really is – and IMO this class is the most important IdentityServer extensibility code you’ll ever write – so own it.

Another confusing thing seems to be our name change – starting with v2 – the Nuget packages are now simply called IdentityServer3.* – we will retire the 1.x feed at some point in the (more distant) future.

All new packages can be found here.

Right before I left, I also sat down with Scott Hanselman to record Hanselminutes. It was about IdentityServer and you can listen to it here.

Up next ist v2.0.1 which includes some bug fixes – it never gets boring!

Posted in .NET Security, ASP.NET, IdentityServer, OAuth, OpenID Connect | Leave a comment

Transitioning from a Token back to a Windows Identity

Sometimes you are in the situation where you have Windows-based users, but the rest of the application architecture is token-based (e.g. using OpenID Connect or WS-Federation). As long as these users stay in your “token-based world” everything is fine. But if you have impersonate those users to talk to Windows authentication-only service (often that’s SQL Server or a file share), you are in trouble.

Historically this was only possible if you were using Kerberos all the way through – and also only over two hops (e.g. browser to web server – web server impersonating browser user to SQL Server). In you token-based architecture there is no Kerberos.

That’s the reason why Microsoft added extensions to Kerberos (actually already back in Windows Server 2003 days) that make it possible to transition from a non-Windows authentication method to a native Windows token (called S4U – services for user).

In essence there is a way to construct a WindowsIdentity just by passing in a Windows account name and get back a Windows token. When you have a WindowsIdentity, you can call Impersonate and impersonate the user. So really the only thing you need to do, is to be able to map the token user back to a Windows user (e.g. via a UPN claims or similar). Job done !?

Hold on – if that would be possible, wouldn’t that completely subvert the Windows security system? Well it is possible, but there are a number hoops you have to jump through.

This comes up every once in a while, and it is always hard to remember all the details. Since I just did that two weeks ago – here’s a brain dump.

  1. First you have to install the “Claims to Windows Token Service” – that’s a Windows service that runs as SYSTEM and thus has enough privileges to create a Windows token that can be impersonated. This service is hidden behind a Windows Server feature called “Windows Identity Foundation”.
  2. You need to configure the Windows service. Since this is such a highly privileged operation (think about it – this service can create Windows tokens for arbitrary users), you need to specify who is allowed to connect to it. This is done in a .config file in the same directory as the service binaries. Add the Windows account of your application that needs to use the service.
  3. Your application account needs an SPN (use the setspn tool to create one).
  4. You need to configure constrained delegation for the application account. This is done in the “Active Directory Users & Computers” tool. On the property pages – use the Delegation tab to configure this account to be “trusted for delegation to specified services only”. Furthermore set the “Use any authentication protocol” option and configure the list of services to which the Windows user identities can be delegated to.

The last step is a tricky part – you also need to create SPNs for the services you want to connect to. The format of theses SPNs depends on the type of service. This document is very helpful to learn about the format for SQL Server.

If all else fail – I always use Wireshark to trace the Kerberos traffic. This will include the requested SPN and makes it easier to figure out the right format.

If everything is configured correctly – you can use the S4UClient class to get the Windows token for the account you want to impersonate:

var id = S4UClient.UpnLogon(“user@domain”);

The easiest way to get S4UClient is by using Nuget.

Afterwards you can impersonate the Windows identity to make the service request:

using (id.Impersonate())
{
// call SQL Server etc..
}

If you get errors saying something like “NT AUTHORITY\ANONYMOUS” authentication has failed authentication, the delegation configuration is incorrect (most possibly the wrong SPN is configured).

Why is this so complicated?
As I said before, this feature allows constructing a valid Windows identity without having to know the password of the user. IOW – this allows impersonating your CEO and make changes to salary database. That’s why.

So you want to make sure that your application, the application account and the server you run on is properly secured.

HTH

(While writing this I always had to think about these two tweets from Enno: this and this.)

Addition Some readers have pointed out, that the “Claims to Windows Token Service” (or short C2WTS) is not really necessary. You just need to give your application account the “Act as part of the Operating System” privilege, and everything is working fine.

That’s true – but you don’t want to give your application that privilege (that’s in essence SYSTEM) – and that’s the actual reason why the C2WTS service was created in the first place.

Posted in .NET Security, ASP.NET | 2 Comments

Simplified ASP.NET and MVC 6 Security Templates

As mentioned before – the ASP.NET templates never really tried to make to you help  understand the security features.  Instead they crammed ever single feature into a single “sample app” making it really hard to figure out who does what (ASP.NET identity vs middleware vs external authentication vs cookie etc).

This created a lot of confusion – and whenever we taught Katana or ASP.NET 5 security, people had this “wow” effect when theyfinally  see the bits and pieces untangled.

That’s why I published my alternative templates that focus on a single security feature at a time on github (work in progress – feel free to send me PRs)

Cookie-based Authentication

External Authentication (e.g. Google)

External Authentication showing the callback technique to run custom logic between external sign-in and local sign-in

HTH

Posted in .NET Security, ASP.NET | Leave a comment