IIS site for both intranet and anonymous users

I am working on an application that should be available to intranet users with their own account (Windows Authentication). It is easy to configure and work.

Now, if users are not logged into the domain (because they are located outside the site or on a device that is not logged in), they should still use the application, minus some personalized features.

So, to summarize, this is what I would like to do:

  • The user opens the application. If Windows credentials are available, the browser sends them to IIS.
  • If user credentials are obtained, the application launches under these credentials (I have it).
  • If user credentials are not obtained, the application runs under an anonymous IIS account, and personalized functions are disabled (I have this covered too).

What I can’t get is not necessarily send credentials. If I turn on Windows authentication, I will be logged in, and that’s fine. However, if I try to access the site without sending credentials, I will get 401, which makes sense. So I turn on anonymous authentication, and now credentials are never sent.

It really makes sense since IIS never requests authentication from a browser. The question is, how do I make this script?

+1
source share
1 answer

You are right in your analysis. Authentication Protocols :

  • Anonymous access
  • Call Answer Authentication
    • Negotiations (Kerberos)
    • NTLM
    • Digest
  • Basic Authentication

In IIS (and most HTTP servers), the authentication process defaults to the order above. i.e. If anonymous access succeeds (details will not be provided here), other authentication providers are ignored, even if they are enabled.

HTTP 401 Challenge

If you want to manage multiple authentication methods and providers, you need to use a mechanism that refuses credentials if you consider them invalid. You can achieve this by sending 401 responses. This is called the HTTP 401 Challenge .

The idea is to inform the client (browser) that the credentials used for the requested resource are rejected.

Depending on the scenario and configuration of the client, the client may handle authentication. And in this case, the authentication process can be different: Challenge-Response providers require a certain number of exchanges to confirm credentials.

In any case, with your anonymous access, the first response 401 will be interpreted by the browser as "authentication is required for this request." The server automatically includes supported authentication providers in the response header if they are included on the server side.

 HTTP/1.1 401 Unauthorized Server: Microsoft-IIS/7.5 WWW-Authenticate: Negotiate WWW-Authenticate: NTLM WWW-Authenticate: Digest qop="auth",algorithm=MD5-sess,nonce="+Upgraded+v1b3a89710edce01754fd608...",charset=utf-8,realm="Digest" WWW-Authenticate: Basic realm="host" X-Powered-By: ASP.NET Content-Length: 0 Proxy-Support: Session-Based-Authentication 

If your browser is configured correctly to send credentials for the zone of your web application (you said that), it will automatically use the first authentication provider that it knows (e.g. NTLM ) and reprocess the request with credentials that it knows ( Windows credentials in your case).

 GET http://host/yourpage.aspx HTTP/1.1 Accept-Encoding: gzip, deflate Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw== Connection: Keep-Alive 

When the authentication process fails, the server will automatically send a 403 Forbidden response to the client to avoid too much traffic. Answer 403 stops the call. The good news is that this requires some task: more than 4. And, as a rule, HTTP authentication requires about 3 maximum answer to a call to succeed (3 for NTLM and 2 for Negotiate -Kerberos- ).

Because you allow anonymous access, the server will not block client requests, and your pages will be called with anonymous credentials. You can interact with your client on your page by setting the HTTP Response Code . As already mentioned, it only works if you have included another authentication provider in addition to Anonymous .

So, the trick is to process it using a counter on your server side and say "if my authentication session / cookie counter is greater than 3, my client cannot authenticate to the server. Let's say it's anonymous."

Some code

I did not do exactly what you need, but you can adapt my code:

  int i = 3; int j = 0; HttpContext httpContext = HttpContext.Current; // Record authentication process HttpCookie httpCookie2 = httpContext.Request.Cookies["loginAttemptCount"]; if (httpCookie2 == null || httpCookie2.Value == String.Empty) { httpCookie2 = new HttpCookie("loginAttemptCount"); } else { j = Int32.Parse(httpCookie2.Value, System.Globalization.CultureInfo.InvariantCulture); } j = (j + 1) % i; string user = Request.ServerVariables["LOGON_USER"]; // Send 401 responses to authenticate the user if (j != 0 && user == String.Empty) { httpCookie2.Value = j.ToString(System.Globalization.CultureInfo.InvariantCulture); httpContext.Response.Cookies.Add(httpCookie2); Response.StatusCode = 401; return; } httpCookie2.Value = String.Empty; httpContext.Response.Cookies.Add(httpCookie2); 

If necessary, you can check the authorization provider in the Authorization header.

 Request.Headers["Authorization"] 

You can use Fiddler to trace your HTTP headers.

Hope this is clear enough.

+3
source

Source: https://habr.com/ru/post/954547/


All Articles