Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows Authentication works on IIS but not Kestrel / Microsoft.AspNetCore.Authentication.Negotiate (not in Chrome, sometimes in Edge, always in IE)?

I created a new Blazor (Server-side) application with Windows Authentication and run it using IIS Express. It will display a message of "Hello Domain\User!" from the following razor component (...\BlazorApp1\BlazorApp1\Shared\LoginDisplay.razor) on top right.

<AuthorizeView>
    Hello, @context.User.Identity.Name!
</AuthorizeView>

If running using Kestrel, the message is not shown. So I tried the following steps to make it work in Kestrel.

  1. Import NuGet package Microsoft.AspNetCore.Authentication.Negotiate

  2. Add the following code in ConfigureService() in Startup.cs.

    services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
  1. Add the following code in Configure() in Startup.cs. They are added between app.UseRouting(); and app.UseEndpoints(...;
            app.UseAuthentication();
            app.UseAuthorization();

It still doesn't show the Hello message. And I read "Anonymous requests are allowed. Use ASP.NET Core Authorization to challenge anonymous requests for authentication." in the document, so I did the following to disable anonymous requests.

In _Host.cshtml, added the following lines after @namespace BlazorApp1.Pages.

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

However, the message is still not displayed? Does it mean the authorization is not working?


Update:

I updated the file ...\BlazorApp1\BlazorApp1\Shared\LoginDisplay.razor to

<AuthorizeView>
    <Authorized>
        Hello, @context.User.Identity.Name!
    </Authorized>
    <NotAuthorized>
        You are not authorized to view that page...
    </NotAuthorized>
</AuthorizeView>

It shows "You are not authorized to view that page...". It seems the Windows Authentication is not working?


Update2:

The following is mentioned in the doc.

Windows environment configuration The Microsoft.AspNetCore.Authentication.Negotiate component performs User Mode authentication. Service Principal Names (SPNs) must be added to the user account running the service, not the machine account. Execute setspn -S HTTP/mysrevername.mydomain.com myuser in an administrative command shell.

I tried to run the following command in Administrator powershell console on my personnel PC at home.

setspn -S HTTP/mypcname myusername

However, it got the error

PS C:\WINDOWS\system32> setspn -S HTTP/desktop8930 nkucw
Ldap Error(0x51 -- Server Down): ldap_connect
Failed to retrieve DN for domain "" : 0x00000051
Warning: No valid targets specified, reverting to current domain.
FindDomainForAccount: Call to DsGetDcNameWithAccountW failed with return value 0x0000054B
Unable to locate account nkucw

Here is the output: (It shows "Authorization was successful." a few times in the log, but the last showes Authorization failed)

info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\nkucw\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\Users\nkucw**strong text**\source\repos\TestPS\BlazorApp1
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed.
info: Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler[12]
      AuthenticationScheme: Negotiate was challenged.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 135.0172ms 401
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/
info: Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler[0]
      None
info: Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler[1]
      Incomplete Negotiate handshake, sending an additional 401 Negotiate challenge.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 16.6473ms 401
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/
info: Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler[0]
      None
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/_Host'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/_Host"}. Executing page /_Host
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /_Host in 206.51090000000002ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/_Host'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 270.6847ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/css/bootstrap/bootstrap.min.css
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/css/site.css
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/_framework/blazor.server.js
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      The file /css/site.css was not modified
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      The file /_framework/blazor.server.js was not modified
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      The file /css/bootstrap/bootstrap.min.css was not modified
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 26.105700000000002ms 304 text/css
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 21.6629ms 304 application/javascript
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 21.6629ms 304 text/css
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/css/open-iconic/font/css/open-iconic-bootstrap.min.css
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      The file /css/open-iconic/font/css/open-iconic-bootstrap.min.css was not modified
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 7.1119ms 304 text/css
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST https://localhost:5001/_blazor/negotiate text/plain;charset=UTF-8 0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/_blazor/negotiate'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/_blazor/negotiate'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 22.780900000000003ms 200 application/json
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/css/open-iconic/font/fonts/open-iconic.woff
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      The file /css/open-iconic/font/fonts/open-iconic.woff was not modified
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/_blazor?id=ase9fodeUXavBCDTwk1Suw
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 7.676900000000001ms 304 application/font-woff
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/_blazor'
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed.

Update3:

Found out it works in Edge, but not in Chrome. Is it a bug of the server-side Blazor?

Update4:

Even with Edge, keeping refreshing the page shows that it may not get the authentication sometimes.

like image 990
ca9163d9 Avatar asked Nov 29 '19 21:11

ca9163d9


People also ask

Does Kestrel support Windows authentication?

Authentication. Negotiate NuGet package can be used with Kestrel to support Windows Authentication using Negotiate and Kerberos on Windows, Linux, and macOS. Credentials can be persisted across requests on a connection.

What is IIS Windows authentication?

Integrated Windows Authentication (IWA) is a built-in Microsoft Internet Information Services (IIS) authentication protocol that can be used to automatically authenticate and sign-in a user to EMS Web App. IWA is best used on intranets where all clients accessing EMS Web App are within a single domain.

How do I use Windows authentication in .NET core API?

For . Start Visual Studio and select Create a new project. In the Create a new project dialog, select ASP.NET Core Web App (or Web API) > Next. In the Configure your new project dialog, enter Project name > Next. In the Additional Information dialog, select Authentication Type as Windows.

How does Windows authentication work in Web API?

Windows authentication enables users to log in with their Windows credentials, using Kerberos or NTLM. The client sends credentials in the Authorization header. Windows authentication is best suited for an intranet environment.


1 Answers

I found your question while tackling a similar issue. I think I know the answer to your problem though - you can use a simple middleware which will challenge the authentication and display the login.

  1. Add this in your Configure method:
app.UseMiddleware<ValidateAuthentication>();
  1. Here is the middleware itself:
internal class ValidateAuthentication : IMiddleware
{
  public async Task InvokeAsync(HttpContext context, RequestDelegate next)
  {
    if (context.User.Identity.IsAuthenticated)
        await next(context);
    else
        await context.ChallengeAsync();
  }
}
  1. And in ConfigureServices :
 services.AddSingleton<ValidateAuthentication>();

You should not need a constructor.

like image 68
Atanas Korchev Avatar answered Sep 21 '22 19:09

Atanas Korchev