5

I'm trying to build a simple ASP.Net Core 2.2 web app that allows AzureAD as an "external provider". I'm doing this in Visual Studio 2019.

As a super-simple demo project, I started by creating a new project that uses Azure AD as the login provider:

  1. Select ASP.NET Core Web Application
  2. Select Web Application (Model-View-Controller)
  3. Change Authentication to "Work or School Accounts". It automatically filled in my domain name (because I'm logged in to VS)

This creates a web application set up to enforce user authentication on all pages. When I run the application, it goes to Azure AD and logs me in prior to navigating to the /home page.

Recall that I said I wanted to add Azure AD as an external provider. So I found this line in Startup.cs:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

and I removed the default authentication scheme to prevent the auto-login, like this:

services.AddAuthentication()
    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

Now, when I run the app, it navigates to the Login page, and it gives me a big blue button offering to let me log in with Azure Active Directory. But clicking on that button does not log me in.

So I scaffolded the Identity pages, and I set a breakpoint at the ExternalLogin GET routine. Sure enough, clicking the big blue button finds its way there. Stepping through the code, I see that the call to _signInManager.GetExternalLoginInfoAsync() returns null.

I'm stuck. Apparently, the (undocumented) configuration magic doesn't set something up correctly to satisfy the call to GetExternalLoginInfoAsync.

Bob.at.Indigo.Health
  • 11,023
  • 13
  • 64
  • 111
  • Let me get this right, what you're saying is that you don't want the single sign on functionality that is provided by the default project and you want your users to be prompted by AzureAD? – Dennis VW Aug 18 '19 at 05:37
  • Since you asked... I have an existing app that allows customers to create accounts (local users, stored in SQL Server). I want to provide a page that lets my employees log in via Azure AD. So, I said to myself, all I need to do is to wire up AzureAD as an "external provider" (rather than Facebook or Google). Once I get that working, I just remove the "big blue button" from the login page and move the "external login" code to a dedicated page. But I can't get AzureAD to play nicely with the built-in Identity pages as an external login provider. – Bob.at.Indigo.Health Aug 18 '19 at 06:01
  • I think you cannot 'not' specify a default scheme, because the sign in manager doesn't know which scheme to use and also your HttpContext.User will never get assigned to. From the Microsoft docs; Define a default scheme if either of the following is true: a) you want the user to be automatically signed in. b) You use the [Authorize] attribute or authorization policies without specifying schemes. The key here being that you probably haven't specified the scheme on the authorize attributes for this to work properly. – Dennis VW Aug 18 '19 at 06:33
  • You can also try adding `services.AddAuthentication(sharedOptions => { sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; })` That might do the trick. – Dennis VW Aug 18 '19 at 06:36
  • You don't want to let user choose use Azure AD or asp.net identity to sign in in identity's default login page , you want to use custom sign-in page instead ? – Nan Yu Aug 19 '19 at 05:51
  • Yes, that's correct. Customers give me username and password to create an account. My employees log in via AzureAD (single tenant - Azure AD logins are allowed only through my corporate domain). – Bob.at.Indigo.Health Aug 19 '19 at 19:22

1 Answers1

1

The scenario is you are using asp.net identity with Azure AD login as external identity provider .

You should set IdentityConstants.ExternalScheme as the signin schema of Azure AD authentication , so that you can get the external user information with _signInManager.GetExternalLoginInfoAsync() :

services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
    .AddDefaultUI(UIFramework.Bootstrap4)
    .AddEntityFrameworkStores<ApplicationDbContext>();

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options => {
    options.SignInScheme= IdentityConstants.ExternalScheme;

    //other config
});

Then you can scaffold the asp.net identity and modify to fit your requirement , in any page trigger external login(OnPost function in ExternalLogin.cshtml.cs) as the default template("big blue button") does .

Nan Yu
  • 26,101
  • 9
  • 68
  • 148