Quote of the Day

more Quotes

Categories

Buy me a coffee

  • Home>
  • security>

About integrated windows authentication and how to implement it in ASP.NET core running on IIS.

Published June 27, 2020 in .NET core , Angular , IIS , security - 4 Comments

In this post, I share what I have learned about integrated windows authentication and how to enable it in a web application which consists of an angular front-end and ASP.NET core 3 backend.

What is integrated windows authentication?

Let me explain by giving an example. At work, my computer is joined to a domain controller, which is basically a server that runs active directory. Joining a domain controller means the domain controller manages my credentials, not my computer. When I login using my windows credentials, my computer communicates with the domain controller to validate my credentials and allow access. We have .NET applications running on IIS on a set of servers that are joined to the domain controller. IIS can check against the domain controller to ensure I have authenticated before granting access. Furthermore, it can work with the browser do so seamlessly without requiring me to enter my credentials because it has built in integrated windows authentication. This is possible because both the server on which IIS runs and the browser on my machine are joined to a same domain controller, and the browser supports the Negotiate authentication scheme. From the document, this is an advantage of integrated windows authentication.

Built into IIS. – Does not send the user credentials in the request. – If the client computer belongs to the domain (for example, intranet application), the user does not need to enter credentials

Integrated Windows Authentication

Hopefully, you now have some ideas about integrated windows authentication. Next, let’s look at how it works.

How does integrated windows authentication work?

Per the document, integrated windows authentication

works with any browser that supports the Negotiate authentication scheme, which includes most major browsers.

Integrated Windows Authentication

The Negotiate authentication scheme is Microsoft’s authentication mechanism which uses Kerberos which is a system that validates a user’s identity based on shared secrets and provides access by issuing tickets.

Here is how it works.

To access a protected resource, the client must present a valid ticket to the server. To obtain the ticket, the client sends a request to a Key Distribution Center (KDC). The client encrypts the request using the user’s credentials. Upon receiving the encrypted request, the KDC retrieves the user’s password from active directory given the username, and uses the password to decrypt the request. By way of encrypting and decrypting the request using the user’s password which the KDC can get from the database, the KDC can verify the user’s identity without having the client sending over the password. Once the client receives the ticket, which the KDC encrypts using a key that it shares with the resource server, the client sends over the ticket to the resource server, which in turn validates the ticket against the KDC using the shared key. Once all the validations are done, the server returns the resource to the client.

The above is just a high level summary. If you want to learn more about Kerberos and see examples, I suggest you watch this short video, read this blog and IETF article.

Hopefully, you now have some ideas about how integrated windows authentication works, let’s discuss when should you use it.

When should you use integrated windows authentication

As a summarize, you should consider using integrated windows authentication if:

  • Both the server and the client machine use Windows and are joined to the same domain controllers.
  • The application is for internal use only. Obviously, if it is accessible by the public, it will not work because the client computers may not use Windows and joined to the domain controllers.
  • The browser supports Negotiate mechanism (most major browsers supports it).
  • The server supports integrated windows authentication. As mentioned in the document, IIS has built in support for integrated windows authentication.

The document mentions integrated windows authentication is susceptible to cross-site request forgery, so just keep this in mind.

Now that you know about integrated windows authentication and how it works, let’s look at how you can implement it in your ASP.NET core application.

In my case, it turns out to be not difficult to configure my application and IIS to use integrated windows authentication. I just have to make a few changes in the app, and enable Windows authentication in IIS.

Changes in applicationhost.config

Set <WindowsAuthentication> to true in applicationhost.config, which is under .vs -> {PROJECT_NAME} -> config directory. The .vs directory is hidden by default, so I enabled the option to show the hidden folders.

      <windowsAuthentication enabled="true">
          <providers>
            <add value="Negotiate" />
            <add value="NTLM" />
          </providers>
        </windowsAuthentication>

See this link for instructions on how to view hidden folder in Windows 10.

Changes in launchSettings.json

In launchSettings.json, which is under Properties folder of the ASP.NET core project, enable WindowsAuthentication under iisSettings:

{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    "iisExpress": {
      "applicationUrl": "http://localhost:61863/",
      "sslPort": 44378
    }
  }
}

Changes in Startup.cs file

  • In Configure(...) method, add these middlewares:
      app.UseAuthentication();
      app.UseAuthorization();

Since the app is an ASP.NET core 3 app, per the document, I put the above middlewares between app.UseRouting() and app.UseEndpoints().

If the app uses authentication/authorization features such as AuthorizePage or [Authorize], place the call to UseAuthentication and UseAuthorizationafterUseRouting and UseCors, but before UseEndpoints:

Migrate from ASP.NET Core 2.2 to 3.0

If you want to learn more, checkout this post on StackOverflow.

In ConfigureServices() method, I added the following:

  services.AddAuthentication(IISDefaults.AuthenticationScheme);
  services.AddAuthorization(); 

Changes on IIS site on remote server

  • In IIS Manager, under Features View of the site, double-click on Authentication feature.
  • Select Windows Authentication and set Status to Enabled.
Enable Windows Authentication on IIS

Changes in angular app

Technically, you don’t need to make any changes in angular for integrated windows authentication to work. Some tutorials online I looked at suggest to add to the header the key and value: withCredentials: true. However, I realized that this is not necessary, and the authentication still work even after I removed the codes.It appears the browser automatically handles the process by the Negotiate authentication scheme.

Optional: Get windows user’s info in angular

It seems as if there is not a way to get info about the windows user from the client app. Therefore, to get the username and status of the windows user, I make the call to the backend.

  • In the asp.net core app, I added the following endpoint to return info about the authenticated user.
[Route("GetAuthenticatedUser")]
        [HttpGet("[action]")]
        public IdentityUser GetUser()
        {
            return new IdentityUser()
            {
                Username = User.Identity?.Name,
                IsAuthenticated = User.Identity != null ? User.Identity.IsAuthenticated : false,
                AuthenticationType = User.Identity?.AuthenticationType
            };
        }

        public class IdentityUser
        {
            public string Username { get; set; }
            public bool IsAuthenticated { get; set; }
            public string AuthenticationType { get; set; }
        }
  • In angular, I added a guard to load the user’s info and validate the user has access before activating the route.
@Injectable()
export class AuthGuardService implements CanActivate {
  constructor(public router: Router, private apiService: ApiService) { }

  canActivate(): Observable<boolean> | Promise<boolean> | boolean {
    return this.apiService.User.pipe(
      take(1),
      switchMap(currentUser => {
        if (!currentUser) {
          return this.apiService.loadUser().pipe(
            take(1),
            switchMap(user => {
            return of(user && user.isAuthenticated);
            }),
            catchError((err: HttpErrorResponse) => {
              if (err) {
                console.error("Failed to load user: " + JSON.stringify(err));
                if (err.status === 403) {
                  this.apiService.setErrorMessage("You don't have access to use this application.");
                }
                else {
                  this.apiService.setErrorMessage("Something went wrong! :(");
                }
              }
              return of(false);
            }));
        }
        return of(currentUser.isAuthenticated);
      }));
  }
}

References

Integrated Windows Authentication

Enable Windows Authentication In Web API And Angular App

What is the difference between Negotiate and NTLM authentication?

Kerberos – authentication protocol

SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows

How to enable Windows authentication for a Web site, Web application, or Web service

4 comments