Particular / ServiceInsight

Advanced debugging for NServiceBus
http://particular.net/serviceinsight
Other
17 stars 32 forks source link

[SPIKE] Attempts at OpenID #1489

Closed DavidBoike closed 2 months ago

DavidBoike commented 2 months ago

This spike was my unsuccessful attempt to connect ServiceInsight to an Azure Container Apps hosted platform secured by Azure Entra ID login.

The attempted scenario is having ServiceControl deployed to Azure Container Apps, reverse-proxied through a ServicePulse container, with Azure Entra ID authentication added by the Container Apps infrastructure.

The attempted solution would have attempted to detect data from the 401 Unauthorized resopnse in the WWW-Authenticate header, and then attempting to complete an OAuth authentication flow using the IdentityModel.OidcClient library.

If that were successful, it would hypothetically be possible to replace the RestSharp authenticator instance from the default NtlmAuthenticator with an OAuth authenticator that would inject the proper headers into further requests. It may have been necessary to add some sort of middleware to handle renewing tokens before they expire.

Problems

The OidcClient wants an "Authority" from which it can load a host of information about what the endpoint supports. In the IdentityModel samples this is always https://demo.duendesoftware.com. Then it adds /.well-known/openid-configuration to that Authority and finds a document where it gets the info it needs.

But from a ServiceInsight connection dialog, we have no idea what the authority will be, given it will be dependent upon waht a customer uses. In my case, I only had the URL https://login.microsoftonline.com/<our-tenant-id>/oauth2/v2.0/authorize but this is only one piece of the puzzle. How does one know what part any given URL is the Authority? In the case of Microsoft login, there is an authority at https://login.microsoftonline.com/<our-tenant-id>/.well-known/openid-configuration. I guess you could keep moving up a directory at a time looking for the config document and then assume that's the authority.

But even trying that, I ran into other problems. The config document hosted by Microsoft, which I am not posting here because I dont' know to what extent our tenant ID should be kept secret, has an issuer defined on https://sts.windows.net/<tentant-id>/ which IdentityClient complained did not match the Authority URL (which is login.microsoftonline.com).

Attempting to circumvent finding the config in the well-known location by pre-filling the ProviderInformation also failed. While it was possible to go through the OAuth flow past logging in on the external browser to the point where the HttpListener on localhost gets the code returned by Microsoft, but it was not possible to turn that code into an access token because of missing information in the configuration.

I chatted with one of the IdentityModel contributors (who I happen to know personally) and he confirmed that the WWW-Authenticate header doesn't always give you the information you need, and you usually need to configure your client application with your Client iD and other parameters anyway. So mostly, the WWW-Authenticate header is useful for finding out you need a token, but not how to get the token.

He also pointed me to this Microsoft documentation about how to find your app's OpenID configuration document URI, which is worth saving.