Skip to content

Beware the combined authorize filter mechanics in ASP.NET Core 2.1

July 15, 2018

In ASP.NET Core 2.1 one of the security changes was related to how authorization filters work. In essence the filters are now combined, whereas previously they were not. This change in behavior is controlled via the AllowCombiningAuthorizeFilters on the MvcOptions, and also set with the new SetCompatabilityVersion API that you frequently see in the new templates.

Prior to 2.1 each authorization filter would run independently and all the authorization filters would need to succeed allow the user access to the action method. For example:

[Authorize(Roles = "role1", AuthenticationSchemes = "Cookie1")]
public class SecureController : Controller
    [Authorize(Roles = "role2", AuthenticationSchemes = "Cookie2")]
    public IActionResult Index()
        return View();

The above code would trigger the first authorization filter and run “Cookie1” authentication, set the HttpContext’s User property with the resultant ClaimsPrincipal, and then check the claims for a role called “role1”. Then, the second authorization filter and run “Cookie2” authentication, overwrite the HttpContext’s User property (thus losing the “Cookie1” user’s claims) with the resultant ClaimsPrincipal, and then check the claims for a role called “role2”. In short, the user had to have both cookies to be granted access. Also, as side effect of this is also that in the action method, the code would only see the claims from “Cookie2”.

With the new compatibility changes in 2.1, the behavior of the above authorization filters has changed. The mechanics are that the authorization filters are now combined (somewhat). The roles are still kept separate, meaning the user must still have both “role1” and “role2”. But the surprising change is that now instead of both schemes being required, now only one is.

What happens is that both “Cookie1” and “Cookie2” are authenticated (if present) and the resultant claims are combined into the one User object. Then the checks for both “role1” and “role2” are done. So if both roles were only in one cookie, then access would be granted. And, of course, in the action method the combined claims from “Cookie1” and “Cookie2” would be available.

This is a different semantic that the way things previously worked. In essence your authorize filter requirements might be relaxed due to the presence of other authorize filters in the action method invocation hierarchy.

A scenario would this might be a issue is where you have an app that has both UI and APIs. A common technique is to use a global filter as a blanket protection to requires that all users be authenticated in the rest of the app:

services.AddMvc(options =>
   var policy = new AuthorizationPolicyBuilder()
   options.Filters.Add(new AuthorizeFilter(policy));

And then an API action method like this:

[Authorize(AuthenticationSchemes = "Bearer")]
public IActionResult PostData()

This new behavior opens us up to possible XSRF attacks on our APIs, whereas pre-2.1 the explicit authentication scheme on the action method protected us.

Now of course, policy schemes (aka virtual schemes), which are also new in 2.1, could help us address this, but that’s a design change in your app.

I agree with the suggestion by Microsoft in the docs that for this new feature:

We recommend you test your application using the latest version (CompatibilityVersion.Version_2_1).

But not so sure about their other comment:

We anticipate that most applications will not have breaking behavior changes using the latest version.

So, beware the side effects of the new combined authorization filter behavior in ASP.NET Core 2.1.


July 9, 2018

In 2014 I developed and released the first version of IdentityManager. The intent was to provide a simple, self-contained administrative tool for managing users in your ASP.NET Identity or MembershipReboot identity databases. It targeted the Katana  framework, and it served its purpose.

But now that we’re in the era of ASP.NET Core and ASP.NET Identity 3 has come to supplant the prior identity frameworks, and it’s time to update IdentityManager for ASP.NET Core. Unfortunately I’ve been so busy with other projects I have not had time. Luckily Scott Brady, of Rock Solid Knowledge, has had the time! They have taken on stewardship of this project so it can continue to live on.

I’m happy to see they have released the first version of IdentityManager2. Here’s a post on getting started. Congrats!


Native OIDC client sample for Windows that uses custom URI scheme handler

January 20, 2018

Since the release of our IdentityModel.OidcClient client library we have had iOS and Android samples for using the system browser to allow a user to authenticate with the token server. Receiving the results from the system browser is interesting since the native client application is in a different process than the system browser. Fortunately those platforms provide an easy way to map a custom URI scheme (used in the client’s redirect_uri) to the native client application. This allows the response parameters from the authorize endpoint to be passed from the system browser into the native client so it can complete the protocol workflow.

Windows also has such a facility, but we never had a sample for it… until now. I just created a sample that does this.

There are two main aspects that are specific to Windows clients. First, the application needs to add certain registry keys to enable this mapping. The sample adds them when it starts. Second, when the browser redirects to the custom URI scheme it launches a new instance of the client application. This means the first instance that initiated the request is still waiting for the response. The second instance needs a mechanism to deliver the results to the first. The sample handles this by using named pipes.

I certainly had to dust off all the Win32 API cobwebs I had rattling around in the back of my brain. Anyway, check it out and hope it helps.

Sponsoring IdentityServer

December 18, 2017

Brock and I have been working on free identity & access control related libraries since 2009. This all started as a hobby project, and I can very well remember the day when I said to Brock that we can only really claim to understand the protocols if we implement them ourselves. That’s what we did.

We are now at a point where the IdentityServer OSS project reached both enough significance and complexity what we need to find a sustainable way to manage it. This includes dealing with issues, questions and bug reports as well as feature and pull requests.

That’s why we decided to set up a sponsorship page on Patreon. So if you like the project and want to support us – or even more important, if you work for a company that relies on IdentityServer, please consider supporting us. This will allow us to be able to maintain…

View original post 6 more words

Slides — Boston Code Camp, Fall 2017

November 19, 2017

Here are the slides for my session “Implementing Authorization forApplications & APIs” from Boston Code Camp. We plan to announce more in January about the code. Thanks for coming!


The userinfo endpoint is not designed for APIs

November 7, 2017

A common (but incorrect) practice I often see people doing is using the OIDC userinfo endpoint from APIs. It seems like a natural thing to want to do — you have an access token in your API and it contains identity scopes. This means the access token can be used at the userinfo endpoint to access the identity data for those scopes (like profile, email, phone, etc.). The problem is that the userinfo endpoint is designed for the client, not the API (after all, userinfo is defined in the OIDC spec, not the OAuth2 spec).

Another way to think of the problem is that the API has no control over the scopes that access token has been granted. The client controls those scopes. This means your API is taking a dependency on the identity information the client is configured to obtain from the token server, and this is quite brittle. If the client ever changes what identity scopes they request, your API is affected.

A better approach is to configure your API to request the claims that it needs for the user. That’s why there’s a UserClaims property on the ApiResource (and Scope) configuration object model(s) in IdentityServer. These configured user claims will be delivered to the API in the access token itself (or from introspection if using reference tokens). This allows your API to be explicit about what it needs about the user, regardless of the client’s configuration.

DevIntersection Las Vegas, October 2017

September 21, 2017

I will be speaking at DEVintersection this October in Las Vegas. The highlight will be the 2-day workshop on “Identity & Access Control for Modern Applications and APIs using ASP.NET Core”. If you register, use promo code “ALLEN” for a discount.

I also have two sessions, one on the fundamentals of OpenID Connect and OAuth2, and another on an introduction to IdentityServer for ASP.NET Core.

Hope to see you there!