SPAs are dead!?

clickbait isn’t it? But this was Brock’s immediate reaction when we saw (and I recommend you read this first):

Full Third-Party Cookie Blocking and More

What this basically means is, that browser are getting more and more strict with how they handle their cookies. The reasons are security (see the recent SameSite changes) and in this case – privacy. Cookies have been exploited for a long time one way or the other – and this is now the reaction of browser vendors.

What does that mean to application architectures? Well – first of all – all these changes only affect cross-site scenarios. But if you are in that situation the immediate consequences will be:

  • front-channel logout notifications do not work anymore (used in pretty much every authentication protocol – like SAML, WS-Fed and OpenID Connect)
  • the OpenID Connect JavaScript session notifications don’t working anymore
  • the “silent renew” technique that was recommended so far to give your application session bound token refreshing don’t work anymore

Safari and Brave are the first browser implementing those changes. Chrome will follow in 2022 (hopefully sooner) etc…

Some things can be fixed, e.g. you can replace front-channel notifications with back-channel ones. Some people recommend replacing silent renew with refresh tokens. This is dangerous advice – even if your token service has implemented countermeasures.

If all the security concerns around storing tokens in browsers did not worry you so far, maybe this is a good reason to consider the BFF architecture for your SPAs (if you are looking for less fancy name – it’s what the BCP calls “JavaScript Applications with a back-end“).

So are SPAs dead? Well – SPAs as in the UI/UX concept certainly not. SPAs as in “browser-based standalone applications that do cross-site authentication and API calls in the context of a modern identity and SSO architectures” – yes.

(and they should be unless we fix some fundamental problems)

my 2c.

Posted in OAuth, OpenID Connect | 7 Comments

Online Workshops in 2020

For obvious reasons, all in-person workshops have been cancelled for the time being.

This is frustrating on one hand, but converting them to an online format, will allow people to attend who otherwise wouldn’t make it. The other upside is, that the prices are lower, and you don’t need to spend money on travel.

Our main training partner, NDC Conferences, has converted their three main events in Europe to online formats, which means I will run our very popular Identity & Access Control for modern Applications using ASP.NET Core 3 workshop as online training on these dates:

  • April 1st/2nd (sign-up here)
  • April 21st/22nd (sign-up here)
  • June 8th/9th (sign-up here)

See here for the complete agenda and hands-on labs as well as any updates to our schedule.

Hopefully we can make this work for everyone! cu there! Keep well!

Posted in Uncategorized | Leave a comment

Mutual TLS and Proof-of-Possession Tokens: Summary

This is the last part of my PoP and Mutual TLS post series.

Part 1 covered some history and motivation, and part 2 looked at various server setups.

Part 3 was supposed to be a walk-through guide on how to set-up ASP.NET Core and IdentityServer, as well as a client and an API.

While writing this up, I realized that this should be really in our documentation rather than on my private blog.

But to summarize those steps, you need to:

  • set-up MTLS at the hosting layer (e.g. IIS, Nginx, Apache etc..)
  • set-up ASP.NET Core to receive the client certificate from the hosting layer if present
  • enable MTLS in IdentityServer
  • associate IdentityServer clients with client certificates

Now the client can start sending the client certificate while requesting tokens and calling APIs. IdentityServer will embed the thumbprint of the client certificate in the access token, and the API will compare that value with the actual client certificate of the TLS layer.

If they match, voila! The client has successfully proven that it is really the owner of the access token – aka Proof-of-Possession.

The full walkthrough including samples etc. can be found here.

Posted in ASP.NET Core, IdentityServer, OAuth, OpenID Connect | 2 Comments

Mutual TLS and Proof-of-Possession Access Tokens – Part 1: Setup

2020 is the year where I want proof-of-possession tokens to become reality. Mutual TLS seems to be the only feasible way to do that today. So here’s another post about it….

This is a two-part post. In this post we will have a look at server-setup to support MTLS, and in the next part we will have a look at ASP.NET and IdentityServer configuration to add support for proof-of-possession access tokens.

The MTLS spec defines two big features:

  • Strong client authentication using a TLS X.509 client certificate
  • Binding access tokens to a TLS X.509 client certificate

Both features can be used either together – or individually.

The spec also allows for two types of client certificates:

  • PKI Mutual-TLS Method: This method assumes an a-priori established trust root and chain-trust certificate validation
  • Self-Signed Certificate Mutual-TLS Method: This method allows establishing trust with a specific certificate, e.g. via the thumbprint

Another technicality is how you are planning to host your MTLS endpoints. Since client certificates get negotiated at connection time, you cannot simply “MTLS enable” your complete web application, since this will have side-effects on other endpoints (e.g. your UI) that don’t need client certificates. This might result in the browser showing “certificate picker” dialogs, which is not desirable.

IIS, e.g. allows to configure the MTLS requirement on a path basis, e.g. /connect/mtls/*. This causes a re-negotiation of the connection, which (I was told) is not optimal, and also not a thing anymore in HTTP/2 going forward. Other servers like Nginx encourage hosting the MTLS endpoints on a different (sub) domain, which seems cleaner to me.

After a long discussion on the OAuth mailing list, the spec added an additional metadata entry called mtls_endpoint_aliases, which allows to point to arbitrary addresses to accommodate different hosting styles.

Over Christmas holidays I was working on the MTLS updates for IdentityServer and tried to setup a test system. This was a more complicated than I thought, so I had to do some additional research which infrastructure has the best support. Here are my results.

Azure App Service

I only had a quick look, but from that, my conclusion was that this only allows to configure MTLS application-wide, and also only supports the PKI MTLS method. This is a show stopper unfortunately.

Update: I got some feedback that this is a bit more flexible than I thought – but not much. Apparently Azure allows to configure exclusion paths for the MTLS config – this sounds like a configuration nightmare to be honest – but is doable I guess. This seems to be the only docs though…

Pure Kestrel

Kestrel allows for both the PKI and self-signed methods – that’s good. But again, only app-wide MTLS settings are supported.


IIS does support scoping the MTLS endpoints to certain paths – but as mentioned above, this does not seem to be favoured approach anymore. The other problem is, that it seems that IIS only supports the PKI MTLS method, or IOW you always need to establish trust to a CA upfront at the OS level – that’s not what I wanted. I had several conversations with Microsoft people about that, and no-one had a solution to that problem. If you know how that would work, I am interested in updating this document.


I never worked with Nginx before, so this was kind of my last resort option. But man, I was shocked how easy it was to get started – and lo and behold, Nginx ticked all the boxes!

With Nginx you would typically setup two sites (or servers in Nginx speak) pointing to the same ASP.NET Core host, e.g. as the main site, and to isolate your MTLS endpoints.

For the general ASP.NET Core setup for Nginx see here.

For the MTLS endpoints, you set-up an additional server that has the following config entries:

ssl_verify_client optional_no_ca;

In this particular case, I accept all MTLS certificates (that’s the no_ca option). You can also configure trusted CAs at the Nginx level.

You then need to configure Nginx to pass the client certificate to your ASP.NET Core application via a header:

proxy_set_header   X-SSL-CERT $ssl_client_escaped_cert;

This will send the certificate as a URL-encoded string on the X-SSL-CERT header, which you then pickup in ASP.NET Core using the certificate forwarding middleware.

I am NOT an Nginx expert – if anyone has some comments on this setup, please let me know!

Hope this helps – in the next post I will have a closer look at the required ASP.NET Core and IdentityServer configuration.

Posted in ASP.NET Core, IdentityServer, OAuth, OpenID Connect | 5 Comments

Hardening OpenID Connect/OAuth Authorize Requests (and Responses)

One of the biggest strengths of OIDC and OAuth is the usage of the browser front-channel. The browser can show a UI and follow redirects, this makes it very powerful and flexible.

Guess what – the biggest weakness of OIDC and OAuth is the browser front-channel. The browser can show a UI and follow redirects, this makes it very vulnerable.

Upon closer inspection, the weakest link (no pun intended) is really the authorize request and response. This is where very important parameters and data are being sent and received. The most common attacks are done by adversaries who can “read but not modify authorize requests and responses”. If they can also modify data and mount additional endpoints, it’s deadly.

In other words, the real question is, how can we retain the enormous advantages of the browser, while making authorize requests/responses more secure?

Plain OAuth 2.0 has nothing to offer here – so let’s start with OpenID Connect.

The “default” mode in OIDC is just like OAuth, where the authorize request parameters are transmitted using unprotected query string parameters – which means data can leak, and is not tamper-proof.

On the other hand, the authorize response in OIDC is always wrapped inside a signed JWT (called the identity token) – either on the browser front-channel in implicit/hybrid scenarios, or on the back channel for code flow.

OIDC also supports the concept of request objects, where the authorize request parameters are wrapped in a JWT, instead using plain query string parameters. Request objects can be transmitted either by value (on a request query string parameter or body field) or by reference using the request_uri parameter. This helps making the parameters tamper proof and adds all the features we like about security tokens like authentication, replay protection and expiration.

What about OAuth?
The above features do not exist in plain OAuth 2.0 – but can be added by the “aftermarket”. Currently specs are in the making to add JWT secured authorize requests (JAR) and responses (JARM). While some details are slightly different compared to the OIDC spec, the intentions are exactly the same – make them tamper proof (and sometimes also confidential).

Of course, this has some consequences. The client must be able to deal with the necessary crypto to create those JWTs, and URLs definitely get longer. Now mix in some more advanced scenarios like additional data in the JWTs (e.g. the new Rich Authorization Requests, aka RAR), URLs are not the optimal transmission vehicle anymore.

Enter by-reference request objects
With this technique the client creates the request object, stores it somewhere where the AS can “download” it, and then simply passes the URL on the request_uri parameter. Sounds easy, but has some real-world challenges, e.g. the AS needs to have access to the location, there needs to be some house-keeping around creating and deleting those files and SSRF (server-side request forgery) is definitely something you have to think about.

Which brings us to the (so far) last step in the evolution of “authorize request hardening” which called Pushed Authorization Requests (PAR). The idea is simple (and great) – basically the AS also acts as a “drop location” for by-reference request objects.

With PAR, the client first pushes all the authorize request parameters via a back-channel connection to the authorization server. This call can utilize all the benefits of back-channels (e.g. strong client authentication or simply no being a front-channel). The AS will then respond with a URI that represents the request parameters (and a time-out).

The front-channel authorize request would then be reduced to:


Thorsten wrote really good blog posts that go into more detail – check them out here and here.

What does that mean for IdentityServer users?
OIDC request objects are supported since version v3. JARs have slightly different validation rules and will be supported in v4. For PAR, we are looking for a sponsor right now, if your company wants that feature, let us know!

Posted in IdentityServer, OAuth, OpenID Connect | Leave a comment

Hardening Refresh Tokens

Refresh tokens provide a UX friendly way to give a client long-lived access to resources without having to involve the user after the initial authentication & token request. This makes them also a high-value target for attackers, because they typically have a much higher lifetime than access tokens.

For confidential clients, refresh tokens are automatically bound to the client via the client secret, this is not the case for public clients. While refresh tokens were historically not allowed for JavaScript-based clients, with the deprecation of the Implicit Flow, it’s technically now possible to also use them in SPA-style scenarios (see the BCP). I’ve already seen a number of popular sites that use them exactly for that purpose.

This post is not about whether you should store access or refresh tokens in a browser (you probably know my opinion about that already), but rather on how to reduce the attack surface of refresh tokens – SPA or not.


It’s a good idea to ask for consent when a client requests a refresh token. This way you at least try to make the user aware of what’s happening, and maybe you also give them a chance to opt-out of it. While this will go at the expense of the user experience, but maybe this is OK for the user.

In IdentityServer we always ask for consent (if enabled) if the client asks for the offline_access scope which goes in-line with the OpenID Connect spec.

Sliding expiration

Refresh tokens usually have a (much) longer lifetime than an access token. You can reduce the exposure though by also adding a sliding lifetime on top of the absolute lifetime. This allows for scenarios where a refresh token can be silently used if the user is regularly using the client, but needs a fresh authorize request, if the client has not been used for a certain time. In other words, they auto-expire much quicker without potentially interfering with the typical usage pattern.

In IdentityServer we support sliding expiration via the AbsoluteRefreshTokenLifetime and SlidingRefreshTokenLifetime client settings.

One-time Refresh Tokens

Another thing you can do, is rotating your refresh tokens on every usage. This also reduces the exposure, and has a higher chance to make older refresh tokens (e.g. exfiltrated from some storage mechanism or a network trace/log file) unusable.

The downside of this approach is, that you might have more scenarios where a legitimate refresh token becomes unusable – e.g. due to network problems while refreshing them.

In IdentityServer this is supported via the RefreshTokenUsage client settings, and we default to one-time only usage.

Replay detection

On top of one-time only semantics, you could also layer replay detection. This means, that if you ever see the same refresh token used more than once, you could revoke all access to the client/user combination. Again – same caveat applies – while increasing the security, this might result in false positives.

We will add this feature in version 4 of IdentityServer.

Additional Token binding

Another technique to consider could be the binding of the refresh token to the client using key material. In access tokens we have the cnf claim for this purpose.

You could apply the same technique to refresh tokens, in other words, if the client has presented some proof key at token request time, refreshing the token could require the same key again. This would go well with the ephemeral MTLS client certificates I wrote about in this blog post. I could see this as a nice additional tool on your belt, especially for public mobile or desktop clients.

There is currently an open issue to define the exact feature set around refresh tokens for vNext of IdentityServer – feel free to chime if you have additional ideas or input.

Posted in IdentityServer, OAuth, Uncategorized | Leave a comment

2020: IdentityServer4 Roadmap

It’s the time of the year – we are working on IdentityServer and lock down the features we want to implement for the next version(s).

Initially we planned to make our 3.0 release the big one – but then .NET Core 3 happened and we had to synchronise our release with Microsoft. That meant we really didn’t have the time to make the changes we wanted to.

This is different for v4 where we have much more control of the schedule. You can imagine that a lot of backlog has accrued over the last year and that many people have many opinions on what we should add or change or fix or whatever. But instead we picked five main themes that we think are important to improve IdentityServer as a whole.

Currently we plan to release 4.0 around June. After that we will work on 5.0 which probably will be released with .NET 5 (December-ish).

So here are the five big things we plan to do:

Make it easier to migrate to different signing algorithms
This is already done – and a more thorough description can be found here.

Make Proof-of-Possession tokens easier to use
Again, this work is already done, see the blog post here.

Update scope and resource design
Our scope validation system is a bit dated and not extensible at all. Our scopes were designed to be static, but newer scenarios like dynamic and structures scopes came up after that. In addition we are adding support for resource indicators which will give you more control over the shape of access tokens. This allows for isolating resources (meaning you can prohibit the issuance of an access token that is valid for more than one resource) and resource specific token content/processing.

Harden Refresh Tokens and make them more secure for SPAs
Refresh tokens in SPAs become a thing (and we can’t stop that). We already have a good feature set around refresh tokens to make them more secure, e.g. sliding expiration and one-time tokens. One missing feature though is detecting multiple refreshes so we can automatically revoke access. This requires some internal changes but it’s worthwhile.

Re-design Logging and Eventing
This is a huge one and might have to be moved to v5. But in essence we want to go fully structured/semantic and also give more control to the implementer – commonly requested features are full control over log levels, redaction of content, transformation of data, splitting of log streams etc… I am strongly leaning towards using the new System.Diagnostics.DiagnosticsListener API for that. Feedback welcome.

Of course there are some smaller issues that might get picked up along the way and you can see a full list here.

As always we encourage you to give feedback and try the new features – we will keep you posted as soon as something is ready.

Posted in IdentityServer, Uncategorized | 2 Comments