microsoft-identity-web
microsoft-identity-web copied to clipboard
[Feature Request] Add `InstanceDiscoveryMetadata` option to `MicrosoftIdentityOptions`
Is your feature request related to a problem? Please describe.
I'm trying to create testing scenarios using MSAL and Playwright for E2E testing.
I'm able to bypass discovery if I overwrite the OnMessageReceived and OnAuthorizationCodeReceived events and create a different ConfidentialClientApplication to be used in the test environment. However, for ease of demonstration I want to configure the application using only the AddMicrosoftIdentityWebApp method.
I am able to get the desired behavior only using AddMicrosoftIdentityWebApp but this only happens after the metadata discovery handlers disable themselves similar to what is reported here.
Describe the solution you'd like A clear and concise description of what you want to happen.
Adding an option that can be set similar to:
// This configuration is only used in a testing environment
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
options.InstanceDiscoveryMetadata = "<MY_METADATA_OR_URL_HERE>";
})
// the rest...
This then makes the ConfidentialClientApplication used by the application configure the metadata using the WithInstanceDiscoveryMetadata method.
Being able to disable metadata discovery outright would be acceptable as well but I'm unsure if this would cause knock-on effects.
// This configuration is only used in a testing environment
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
options.EnableMetadataDiscovery = false;
})
// the rest...
Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.
I am able to bypass this issue already by going to a lower level but I'm really hoping to be able to show case an easy to use testing scenario with these 'out of the box' methods like AddMicrosoftIdentityWebApp when creating the application.
Additional context Add any other context or screenshots about the feature request here.
See discussion here. When writing these tests I am using servers on localhost to provide spoofed data such as ID tokens, metadata and graph data. No HTTP calls are being made outside of the local network (aside from the metadata discovery which I'd like to disable or configure).
@v-michaelmi : I think I understand your need, but have a few questions:
- is the instance discovery that you want to prevent happening in MSAL? Or before (done by ASP.NET OpenIdConnect middleware). If it's happening only on MSAL when it redeems the auth code, then it would be better to have the option in ConfidentialClientApplication? (When you execute: EnableTokenAcquisitionToCallDownstreamApi)
- Why do you want to prevent the instance discovery? I don't fully understand why it's necessary to do end to end tests? Or aren't they end to end?
Hey @jmprieur,
To your first question, I started playing around a bit more and I'm noticing that the instance discovery is not happening if I don't run EnableTokenAcquisitionToCallDownstreamApi.
When I run the code below I'm able to create sessions and have claims from my tokens set as expected.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
// ...
options.Events.OnAuthorizationCodeReceived async context => {
// Handle spoofed token acquisition here.
};
// ...
});
When I run the code below the application hangs and it tries to run discovery at loigin.microsoftonline.com:5001 (which is the port for my application) similar to what's reported in this issue
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
// Configurations
})
.EnableTokenAcquisitionToCallDownstreamApi(intialScopes)
.AddInMemoryTokenCaches();

To your second question, the major reason I want to prevent instance discovery is to enable testing for an application in a local environment which is independent of Azure. The idea is that if I want to test specific scenarios, say a consent issue comes up for a certain feature or there's an internal server error, I'd be able to send a mock response to the application similar to what would be received from Azure and test that the client-side behavior is executing correctly.
If instance discovery runs the testing will not work until the instance discovery disables itself after about 3-5 minutes.
@v-michaelmi for your first question, what instance / authority do you use in your appsettings.json? I don't understand why ESTS is contacted with the port of your application?
For the second question. Got it, thanks
@jmprieur
I'm not sure either.
My instance is set to https://localhost:5001/5c938525-191e-4e24-8a10-705398cffd57/.
The appsettings.json file used is below.
{
"AzureAd": {
"Instance": "https://localhost:5001/5c938525-191e-4e24-8a10-705398cffd57/",
"TenantId": "5c938525-191e-4e24-8a10-705398cffd57",
"ClientId": "2e84d8aa-dbde-49f4-bc34-0cbd7923758d",
"ClientSecret": "MY_MADE_UP_SECRET",
},
"DownstreamApi": {
"BaseUrl": "https://localhost:5001/5c938525-191e-4e24-8a10-705398cffd57/",
"Scopes": "user.read"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
@v-michaelmi : you mean you have your own STS?
@jmprieur for the sake of this conversation yes 😄
Can follow up with you on the specifics for a project I'm working with a few others on if you like. In this particular case it's trivial and meant to provide some simple tokens to bypass login prompts and test certain scenarios without having to change the application code itself.
Instance discovery should not use the port indeed for the instance discovery process, but should use it for /authorize and /token endpoint. Does that make sense? If yes, please transfer this bug to MSAL.
Related issue: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/1292
@bgavrilMS
What you're saying makes sense but the issue is that I'm trying to use my localhost as the metadata discovery endpoint. I don't want to send requests to login.microsoftonline.com.
I'm able to configure this at the higher ends of the application but when I run EnableTokenAcquisitionToCallDownstreamApi it tries to make a discovery call to login.microsoftonline.com.
Ack, then this feature request makes sense.
Alternative to this would be to set "validate authority" flag to false. A request to login.microsoftonline.com will still happen but invalid_authority error will be ignored.