Recently we ran into an issue at one of my clients when integrating an ASP.NET Core application with an IDP using the OpenID Connect middleware. When running the application locally everything worked as expected: the middleware takes care of most of the hard work as far as generating the calls the authorization & token endpoints, validating the tokens, signing in, … is concerned. But when deploying the solution, we ran into “Correlation failed” errors. More specifically: the exception stated “State property not found”. The environment we were deploying to was of course different from a local dev environment. As is the case in most companies, we’re talking reverse proxy, load balancers, …
So we enabled additional logging, dived into the source code and found out that the culprit was the StateDataFormat.Unprotect(message.State) call which failed. In case you’re not familiar with this: this is part of ASP.NET Core’s new Data Protection APIs, and the middleware uses these. In short: state is encrypted by the middleware before sending it to the IDP. When the IDP posts back to the web app, it posts back the encrypted state, which must then be decrypted by the middleware for further use.
Decryption failed, resulting in a null state, which then resulted in that “Correlation failed: state property not found” error.
Turns out the middleware tried to decrypt the state with a different key than the one that was used for encryption. By default, the keys are stored in the %LOCALAPPDATA% location on the server. When you’re behind a load balancer, requests have tendency to end up on different servers, thus resulting in different keys being used. Once we were sure of the reason, the solution was easy: we stored the keys on a file system share instead of on each server.
public void ConfigureServices(IServiceCollection services)
Hope this helps some of you out. Happy coding!