AzureAD / microsoft-identity-web

Helps creating protected web apps and web APIs with Microsoft identity platform and Azure AD B2C
MIT License
684 stars 217 forks source link

Microsoft.Identity.Web.OWIN issue with AD B2C #2312

Closed dmhiggins23 closed 1 year ago

dmhiggins23 commented 1 year ago

Microsoft.Identity.Web Library

Microsoft.Identity.Web.OWIN

Microsoft.Identity.Web version

2.12.4

Web app

Sign-in users

Web API

Not Applicable

Token cache serialization

In-memory caches

Description

I've been working towards using Microsoft.Identity.Web to use AD B2C for authentication in an OWIN project. It does not appear to be adding the SignUpSignInPolicyId to the url during the initial back channel query to the server.

Reproduction steps

I've recreated a minimal version of the project at https://github.com/AzureAD/microsoft-identity-web/tree/master/tests/DevApps/aspnet-mvc/OwinWebApp

This is the startup code:

Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
OwinTokenAcquirerFactory factory = TokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>();
app.AddMicrosoftIdentityWebApp(factory);
factory.Services
    .Configure<ConfidentialClientApplicationOptions>(options => { options.RedirectUri = "https://localhost:44300/"; })
//    .AddMicrosoftGraph()
//    .AddDownstreamApi("DownstreamAPI1", factory.Configuration.GetSection("DownstreamAPI"))
    .AddInMemoryTokenCaches();
factory.Build();

I'm using a appsettings.json config file to store the configuration information.

If I configure it as an active directory application (i.e., not B2C), it works fine. When I hit the protected action I get the login prompt and can log in.

When I configure the appsettings.json as a AD B2C app, I get the following exception

IDX20807: Unable to retrieve document from: 'https://<DOMAIN_NAME>.b2clogin.com/<DOMAIN_NAME>.onmicrosoft.com/v2.0/.well-known/openid-configuration'. HttpResponseMessage: 'StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
 X-Frame-Options: DENY
 Public: OPTIONS,TRACE,GET,HEAD,POST
 Strict-Transport-Security: max-age=31536000; includeSubDomains
 X-Content-Type-Options: nosniff
 X-XSS-Protection: 1; mode=block
 Date: Mon, 26 Jun 2023 15:46:00 GMT
 Content-Length: 103
 Allow: OPTIONS
 Allow: TRACE
 Allow: GET
 Allow: HEAD
 Allow: POST
 Content-Type: text/html
}', HttpResponseMessage.Content: 'The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.'.

If I pull the url from this exception, namely https://<DOMAIN_NAME>.b2clogin.com/<DOMAIN_NAME>.onmicrosoft.com/v2.0/.well-known/openid-configuration and append the sign in policy id to it as follows https://<DOMAIN_NAME>.b2clogin.com/<DOMAIN_NAME>.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_SignUp_SignIn, and visit that url in a browser, the browser retrieves the same document as I get when go to the "Run User Flow" section of the azure portal for that directory.

I've added the following code to startup after the call to factory.build

var msIdentityOptio2nsContainer = factory?.ServiceProvider?.GetRequiredService<Microsoft.Extensions.Options.IOptions<Microsoft.Identity.Abstractions.MicrosoftIdentityApplicationOptions>>();
var msidOptions = msIdentityOptio2nsContainer.Value;
string json = System.Text.Json.JsonSerializer.Serialize(msidOptions);
System.Diagnostics.Debug.WriteLine(json);

This produces the following output, reflecting at least a part of the the loaded configuration (i.e. MicrosoftIdentityApplicationOptions).

{
    "Instance": "https://<DOMAIN_NAME>.b2clogin.com/",
    "TenantId": "<DOMAIN_NAME>.onmicrosoft.com",
    "Authority": "https://<DOMAIN_NAME>.b2clogin.com/<DOMAIN_NAME>.onmicrosoft.com/v2.0",
    "AzureRegion": null,
    "ClientCapabilities": null,
    "SendX5C": false,
    "WithSpaAuthCode": false,
    "Domain": "<DOMAIN_NAME>.onmicrosoft.com",
    "EditProfilePolicyId": null,
    "SignUpSignInPolicyId": "B2C_1_SignUp_SignIn",
    "ResetPasswordPolicyId": null,
    "DefaultUserFlow": "B2C_1_SignUp_SignIn",
    "ResetPasswordPath": "/MicrosoftIdentity/Account/ResetPassword",
    "ErrorPath": "/MicrosoftIdentity/Account/Error",
    "ClientId": "<CLIENT_ID>",
    "EnablePiiLogging": false,
    "ExtraQueryParameters": null,
    "ClientCredentials": null,
    "Audience": null,
    "Audiences": null,
    "TokenDecryptionCredentials": null,
    "AllowWebApiToBeAuthorizedByACL": false
}

The appsettings.json file contains:

{
  "AzureAd": {
    "Instance": "https://<DOMAIN_NAME>.b2clogin.com/",
    "Domain": "<DOMAIN_NAME>.onmicrosoft.com",
    "TenantId": "<DOMAIN_NAME>.onmicrosoft.com",
    "ClientId": "<CLIENT_ID>",
    "RedirectUri": "https://localhost:44300",
    "ClientSecret": "<CLIENT_SECRET>",
    "SignUpSignInPolicyId": "B2C_1_SignUp_SignIn"
  }
}

For the sake of completeness, here is packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Antlr" version="3.4.1.9004" targetFramework="net48" />
  <package id="Azure.Core" version="1.24.0" targetFramework="net48" />
  <package id="Azure.Identity" version="1.3.0" targetFramework="net48" />
  <package id="Azure.Security.KeyVault.Certificates" version="4.1.0" targetFramework="net48" />
  <package id="Azure.Security.KeyVault.Secrets" version="4.1.0" targetFramework="net48" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net48" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNet.WebApi.HelpPage" version="5.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
  <package id="Microsoft.AspNetCore.Cryptography.Internal" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.AspNetCore.DataProtection" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.AspNetCore.DataProtection.Abstractions" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.AspNetCore.Hosting.Abstractions" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.AspNetCore.Hosting.Server.Abstractions" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.AspNetCore.Http.Abstractions" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.AspNetCore.Http.Features" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net48" />
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net48" />
  <package id="Microsoft.Extensions.Caching.Abstractions" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.Extensions.Caching.Memory" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.Extensions.Configuration" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Extensions.Configuration.Abstractions" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Extensions.Configuration.Binder" version="3.1.3" targetFramework="net48" />
  <package id="Microsoft.Extensions.Configuration.FileExtensions" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Extensions.Configuration.Json" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Extensions.DependencyInjection" version="3.1.3" targetFramework="net48" />
  <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="3.1.3" targetFramework="net48" />
  <package id="Microsoft.Extensions.FileProviders.Abstractions" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Extensions.FileProviders.Physical" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Extensions.FileSystemGlobbing" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Extensions.Hosting" version="2.1.1" targetFramework="net48" />
  <package id="Microsoft.Extensions.Hosting.Abstractions" version="2.1.1" targetFramework="net48" />
  <package id="Microsoft.Extensions.Http" version="3.1.3" targetFramework="net48" />
  <package id="Microsoft.Extensions.Logging" version="3.1.3" targetFramework="net48" />
  <package id="Microsoft.Extensions.Logging.Abstractions" version="3.1.3" targetFramework="net48" />
  <package id="Microsoft.Extensions.Options" version="3.1.3" targetFramework="net48" />
  <package id="Microsoft.Extensions.Options.ConfigurationExtensions" version="2.1.0" targetFramework="net48" />
  <package id="Microsoft.Extensions.Primitives" version="3.1.24" targetFramework="net48" />
  <package id="Microsoft.Graph" version="4.34.0" targetFramework="net48" />
  <package id="Microsoft.Graph.Core" version="2.0.9" targetFramework="net48" />
  <package id="Microsoft.Identity.Abstractions" version="3.2.0" targetFramework="net48" />
  <package id="Microsoft.Identity.Client" version="4.54.1" targetFramework="net48" />
  <package id="Microsoft.Identity.Client.Extensions.Msal" version="2.16.5" targetFramework="net48" />
  <package id="Microsoft.Identity.Web.Certificate" version="2.12.4" targetFramework="net48" />
  <package id="Microsoft.Identity.Web.Certificateless" version="2.12.4" targetFramework="net48" />
  <package id="Microsoft.Identity.Web.Diagnostics" version="2.12.4" targetFramework="net48" />
  <package id="Microsoft.Identity.Web.OWIN" version="2.12.4" targetFramework="net48" />
  <package id="Microsoft.Identity.Web.TokenAcquisition" version="2.12.4" targetFramework="net48" />
  <package id="Microsoft.Identity.Web.TokenCache" version="2.12.4" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Abstractions" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.JsonWebTokens" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Logging" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.LoggingExtensions" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Protocols" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Protocols.OpenIdConnect" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Protocols.WsFederation" version="5.5.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Tokens" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Tokens.Saml" version="5.5.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Validators" version="6.30.0" targetFramework="net48" />
  <package id="Microsoft.IdentityModel.Xml" version="5.5.0" targetFramework="net48" />
  <package id="Microsoft.Owin" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Owin.Security" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Owin.Security.ActiveDirectory" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Owin.Security.Cookies" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Owin.Security.Jwt" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Owin.Security.OAuth" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Owin.Security.OpenIdConnect" version="4.2.2" targetFramework="net48" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
  <package id="Microsoft.Win32.Registry" version="4.5.0" targetFramework="net48" />
  <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
  <package id="Owin" version="1.0" targetFramework="net48" />
  <package id="System.Buffers" version="4.5.1" targetFramework="net48" />
  <package id="System.ComponentModel.Annotations" version="4.7.0" targetFramework="net48" />
  <package id="System.Diagnostics.DiagnosticSource" version="4.7.1" targetFramework="net48" />
  <package id="System.Drawing.Common" version="4.7.2" targetFramework="net48" />
  <package id="System.IdentityModel.Tokens.Jwt" version="6.30.0" targetFramework="net48" />
  <package id="System.IO" version="4.3.0" targetFramework="net48" />
  <package id="System.Memory" version="4.5.4" targetFramework="net48" />
  <package id="System.Memory.Data" version="1.0.2" targetFramework="net48" />
  <package id="System.Net.Http" version="4.3.4" targetFramework="net48" />
  <package id="System.Net.Http.WinHttpHandler" version="6.0.1" targetFramework="net48" />
  <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
  <package id="System.Runtime" version="4.3.0" targetFramework="net48" />
  <package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
  <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net48" />
  <package id="System.Security.AccessControl" version="4.7.0" targetFramework="net48" />
  <package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net48" />
  <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net48" />
  <package id="System.Security.Cryptography.Pkcs" version="7.0.2" targetFramework="net48" />
  <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net48" />
  <package id="System.Security.Cryptography.ProtectedData" version="4.5.0" targetFramework="net48" />
  <package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net48" />
  <package id="System.Security.Cryptography.Xml" version="4.7.1" targetFramework="net48" />
  <package id="System.Security.Permissions" version="4.7.0" targetFramework="net48" />
  <package id="System.Security.Principal.Windows" version="4.7.0" targetFramework="net48" />
  <package id="System.Text.Encoding" version="4.3.0" targetFramework="net48" />
  <package id="System.Text.Encodings.Web" version="6.0.0" targetFramework="net48" />
  <package id="System.Text.Json" version="6.0.4" targetFramework="net48" />
  <package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
  <package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
  <package id="WebGrease" version="1.5.2" targetFramework="net48" />
</packages>

Is there a working version of Microsoft.Identity.Web.Owin being used to access a B2C directory?

I cannot determine if this is an error in my code, a bug in Microsoft.Identity.Web.Owin, or a known limitation of Microsoft.Identity.Web. Any guidance would be greatly appreciated.

Error message

No response

Id Web logs

No response

Relevant code snippets

Included above

Regression

No response

Expected behavior

retrieve open id connect data from server

jmprieur commented 1 year ago

@dmhiggins23 : b2c is supported in OWIN web APIs, but not yet in web apps. It's on the backlog, but not super high priority.

Did you consider Microsoft Entra External IDs. Assuming you are building a new app?

dmhiggins23 commented 1 year ago

Thanks Jean-Marc, unfortunately I am locked into an Orchard CMS 1.10 project. I have a large code base written against that platform with a couple of existing production sites.