Bob.at.Indigo.Health
Bob.at.Indigo.Health

Reputation: 11895

Log in with Azure AD and get a UserManager

I have two websites, a "customer" website that contains local users stored in Identity tables in a SQL Server database, and a "management" website the logs in users via our Azure AD. Both websites share a common view of the SQL database (I put the migrations and DbContext in a shared library).

My management website wants to automatically redirect users to Azure AD if they are not authenticated. This is done in Startup.cs via:

// Use AzureAD for authentication
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

So far, so good... The above code causes the website to automatically log in via my Azure AD.

Now for the complication: Code in the the management website wants to manipulate "Identity" users created by the "customer" website. To do this, the management website needs UserManager and RoleManager instances. But the only way I know to wire up a UserManager or a 'RoleManager' is to call AddIdentity or AddDefaultIdentity, like this:

// Configure Identity
services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

// Use AzureAD for authentication
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

This allows me to use DI to get a UserManager or RoleManager instance elsewhere in the code, but it turns off the automatic login via Azure AD and tries to redirect to the Identity login page (which, in my "management" website, doesn't exist).

How can I configure Identity while retaining the automatic Azure AD login behavior?

EDIT:

Microsoft tech support is working on this. I'll post the answer when I get it from them.

Upvotes: 1

Views: 2066

Answers (2)

Aditya
Aditya

Reputation: 56

Use AddIdentityCore and inject UserManager and RoleManager separately like below

services.AddIdentityCore<AppUser>(options => 
    options.SignIn.RequireConfirmedAccount = false)
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<AppUserContext>();

services.AddScoped<UserManager<AppUser>>();
services.AddScoped<RoleManager<IdentityRole>>();
services.AddScoped<IRoleStore<IdentityRole>, RoleStore<IdentityRole, ApplicationDbContext>>();

Reference on AddIdentityCore

Difference between AddIdentity and AddIdentityCore Refer

Github sample here

Upvotes: 3

sprengo
sprengo

Reputation: 168

It seems that Identitys authentication theme Identity.Application is used in the default authorization policy for your authorized controllers. Try to explicitly set the default authorization policy to use the AzureAD authentication theme, e.g.:

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(AzureADDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build();
});

Edit: Have a look at the AddIdentity extension method in IdentityServiceCollectionExtensions.cs on GitHub, within that method AddAuthentication is called:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})

Perhaps you have to overwrite these settings with the corresponding constants from the AzureADDefaults in the AddAuthentication call on which you call AddAzureAd like:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = AzureADDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = AzureADDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = AzureADDefaults.CookieScheme; // not sure
})
    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

Upvotes: 0

Related Questions