1

I have an Azure App Service Running a Web Application (NOT a single page app and NOT using MSAL). I am using C# MVC ASP.NET CORE I am using the MicrosoftIdentityWebAppAuthentication service.

My authentication currently works perfectly however, I have a senario where I need the authentication to happen in a popup window instead of redirecting to a new page for the authentication and back again.

I know popup authentication can be accomplished with a single page app and MSAL.js but I dont want to start again. I am open to options for a hybrid approch but I would like to stay with my current authentication process if possible.

Can the services.AddMicrosoftIdentityWebAppAuthentication(Configuration) be extended to include a popup window?

Here is a snippet from my startup.cs file:


public void ConfigureServices(IServiceCollection services) {
            services.AddOptions();

            var graphBaseUrl = Configuration["Graph:BaseUrl"]; //"https://graph.microsoft.com/v1.0";
    
            var userReadScope = "user.read";
    
            string[] initialScopes = new string[] { userReadScope };
    
            services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
                            .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                            .AddMicrosoftGraph(graphBaseUrl, userReadScope)
                            .AddSessionTokenCaches();
    
            services.AddControllersWithViews(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            }).AddMicrosoftIdentityUI();
    
            services.AddRazorPages();

}

Ive tried to create a hybrid with MSAL.js but I could not figure out how to merge them.

Ken Newman
  • 31
  • 2

1 Answers1

2

Authentication in a popup window using MSAL.js in conjunction with the MicrosoftIdentityWebAppAuthentication service in an ASP.NET Core MVC app.

  • In _Layout.cshtml file, add the below script tags to include the MSAL.js library.
<!DOCTYPE html>
<html>
<head>
   @await Microsoft.AspNetCore.Identity.UI.Services.CdnScripts.IncludeAsync(User)
</head>
<body>
   @await Microsoft.AspNetCore.Identity.UI.Services.CdnScripts.IncludeAsync(User)
</body>
</html>
  • Add a new JavaScript file with auth-popup.js to your wwwroot/js folder.
var msalConfig = {
    auth: {
        clientId: 'Client_Id',
        authority: 'AZURE_AD_AUTHORITY',
        redirectUri: 'REDIRECT_URI',
        navigateToLoginRequestUrl: false
    },
    cache: {
        cacheLocation: 'localStorage',
        storeAuthStateInCookie: false
    }
};

var msalInstance = new msal.PublicClientApplication(msalConfig);

function openAuthPopup() {
    msalInstance.loginPopup()
        .then(response => {
          })
        .catch(error => {
            console.log(error);
        });
}
  • In Startup.cs file to inject the ITokenAcquisition interface into your controllers. Modify the ConfigureServices method as shown below.
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;

public void ConfigureServices(IServiceCollection services)
{
        services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
        .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
        .AddMicrosoftGraph(graphBaseUrl, userReadScope)
        .AddSessionTokenCaches();

    services.AddControllersWithViews(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
    })
    .AddMicrosoftIdentityUI();

    services.AddRazorPages();
  
    services.AddScoped<ITokenAcquisition>(provider =>
    {
        var httpContextAccessor = provider.GetRequiredService<IHttpContextAccessor>();
        var tokenAcquisition = provider.GetRequiredService<ITokenAcquisition>();
        tokenAcquisition.HttpContextAccessor = httpContextAccessor;
        return tokenAcquisition;
    });
}
  • In your view, add a button for triggering the openAuthPopup() function.
@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>    
    <button onclick="openAuthPopup()">Authenticate</button>
</div>

@section Scripts {
    <script src="~/js/auth-popup.js"></script>
}

For more information, refer to MSDoc and SO link.

Rajesh Mopati
  • 1,329
  • 1
  • 2
  • 7
  • Thank you so much for your solution!! For tokenAcquisition.HttpContextAccessor = httpContextAccessor; I am getting an error that says: itokenacquisition does not contain a definition for HttpContextAccessor.. – Ken Newman Jun 23 '23 at 14:19
  • Rajesh do you have any thoughts on this error I am getting? – Ken Newman Jun 24 '23 at 20:03
  • The error you're encountering suggests that the ITokenAcquisition interface does not have a property named HttpContextAccessor. The HttpContextAccessor is part of the ASP.NET Core framework and is typically used to access the current HttpContext within a web application. – Rajesh Mopati Jun 25 '23 at 03:21
  • If you want to access the HttpContext in your custom code, you can inject the IHttpContextAccessor into your class. – Rajesh Mopati Jun 25 '23 at 03:22
  • I just upgraded to .Net 7 to see if It might resolve some issues. It now recognizes Microsoft.AspNetCore.Identity.UI but for the line: @await Microsoft.AspNetCore.Identity.UI.Services.CdnScripts.IncludeAsync(User) I am getting the Error: Error CS0234 The type or namespace name 'CdnScripts' does not exist in the namespace 'Microsoft.AspNetCore.Identity.UI.Services' (are you missing an assembly reference?) Any thoughts? – Ken Newman Jun 28 '23 at 17:52
  • The error message you are seeing indicates that the CdnScripts namespace is not found in the Microsoft.AspNetCore.Identity.UI.Services namespace. One possible solution is to add a reference to the `Microsoft.AspNetCore.Identity.UI` package in your project. You can do this by adding the following line to your project file. – Rajesh Mopati Jun 29 '23 at 03:39