Active Directory B2C and OpenIdConnectAuthenticati

2019-08-11 09:32发布

I have set up two tenants, 123.onmicrosoft.com and abc.onmicrosoft.com.

I have developed a web application using OpenIdConnectAuthenticationMiddleware to do the OpenID Connect authentication flow.

The out-of-the-box middleware requires the client ID to be passed during the configuration of the OWIN middleware, this is our challenge. Our web application is deployed once using two bindings: 123.mydomain.com and abc.mydomain.com.

We want to set the client ID at runtime. Our current approach was to develop a subclass and inject a function to gather the client ID at runtime, something like this:

public class LendingMiddleware : OpenIdConnectAuthenticationMiddleware
{
    private Action<IOwinContext, OpenIdConnectAuthenticationOptions> _optionBuilder = null;
    public LendingMiddleware(OwinMiddleware next, IAppBuilder app,
        OpenIdConnectAuthenticationOptions options,
        Action<IOwinContext, OpenIdConnectAuthenticationOptions> optionBuilder = null) : base(next, app, options)
    {
        _optionBuilder = optionBuilder;
    }

    public LendingMiddleware(OwinMiddleware next, IAppBuilder app, OpenIdConnectAuthenticationOptions options) : base(next, app, options)
    {
    }

    public override async Task Invoke(IOwinContext context)
    {
        _optionBuilder?.Invoke(context, Options);
        await base.Invoke(context);
    }

}

On start up class we add two middleware: UseTenantVerification read the host header to load the application configuration associated to this tenant. LendingAuthentication use LendingMiddleware to do the openid flow, lending Middleware inherid from OpenIdConnectAuthenticationMiddleware

public void ConfigureAuth(IAppBuilder app)
{
    //fixed address for multitenant apps in the public cloud
    string authority = "https://login.microsoftonline.com/common/";

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    app.UseCookieAuthentication(new CookieAuthenticationOptions { });
    app.UseTenantVerification();

    app.UseLendingAuthentication(CreateOptions(authority), (ctx, options) =>
    {
        TenantConfig tc = ctx.Environment["TenantInfo"] as TenantConfig;
        options.ClientId = tc.ClientId;
        options.TokenValidationParameters.ValidAudience = tc.ClientId;
        //ctx.ProtocolMessage.Password = tenantConfig.Secret;
    });
}

TenantConfig looks like this:

public TenantConfig GetTenantConfig(string httpHost)
{
    IDictionary<string, TenantConfig> Tenants = new Dictionary<string, TenantConfig>();
    Tenants.Add(new KeyValuePair<string, TenantConfig>("123.local", new TenantConfig
    {
        ClientId = "90677fe0-412c-4625-8d45-f37c14ffb456",
        Secret = "[secret!]",
        HostName = "123.local",
        ApiResources = new Dictionary<string, ApiResourceConfig>
        {
            {
                "TodoWebApi", new ApiResourceConfig
                {
                    ResourceIdentifier = "https://123.onmicrosoft.com/TodoWebApiMT",
                    ResourceAddress = "http://TodoWebApiMT.local"
                }
            }
        }
    }));

    Tenants.Add(new KeyValuePair<string, TenantConfig>("abc.local", new TenantConfig
    {
        ClientId = "000309f7-ac34-4fb6-a833-ef7c664e0958",
        Secret = "[secret!]",
        HostName = "abc.local",
        ApiResources = new Dictionary<string, ApiResourceConfig>
        {
           {
                "TodoWebApi", new ApiResourceConfig
                {
                    ResourceIdentifier = "https://abc.onmicrosoft.com/TodoWebApiMT",
                    ResourceAddress = "http://TodoWebApiMT.local"
                }
            }
        }
    }));

    var k = Tenants.Keys.First(item => item.Equals(httpHost));
    return Tenants[k];
}

We keep the client ID, app key and the API resources that this tenant would want to access. We have only one API app for now but eventually it will be a few API apps that would be added to the tenant directory to grant access.

Is there a better way to do this?

0条回答
登录 后发表回答