0

I have an ASP.NET application (on .NET 4.5.2) where I want to use combined Windows authentication and JWT token auth.

When the app starts, it calls an endpoint like this:

/api/auth/token

This endpoint uses Windows authentication to get the current user, generate a JWT token, and return it to the frontend. This part works fine — the token is successfully generated and returned.

However, when I make the next API call (for example to /api/tickets), which uses a [CustomAuthorization] attribute to validate the JWT token, the browser immediately opens the Windows sign-in popup again.

After I enter my credentials, the request hits the Application_BeginRequest method, and then loops back to the sign-in popup. It never reaches the actual controller method.

It seems like Windows authentication is still being triggered for all requests, even though subsequent requests are supposed to use only the JWT token for authorization.

How I configure my first endpoint:

[HttpGet] 
[Route("token")] 
public IHttpActionResult GetToken() 
{    
    try
    {         
        ClaimsPrincipal claims;         
        var httpUser = HttpContext.Current?.User as ClaimsPrincipal;
    }
    catch()
    { }
}

Everything is fine and this method returns a token, but somehow the next endpoint like this:

[HttpPost]  
[Route("testuser")]  
[CustomAuthorization]  
public HttpResponseMessage GetTestUser()  
{
     // ...
}

never is being hit. The CustomAuthorization just get token from header and validates it.

I have RestangularProvider.setDefaultHttpFields({ withCredentials: true }); in the frontend.

I have this config in my web.config file:

<system.web>   
    <authentication mode="Windows" />   
    <compilation debug="true" targetFramework="4.5.2" />   
    <httpRuntime targetFramework="4.5.2" /> 
</system.web>

When I add this:

<system.webServer>  
    <security>       
        <authentication>         
            <windowsAuthentication enabled="true" />
            <anonymousAuthentication enabled="true" />       
        </authentication> 
    </security>
</system.webServer>  

I get a problem with CORS.

Addition: I checked the request and here is what happens,

the problematic endpoint is called twice:

First as an OPTIONS request (CORS preflight) – it returns 200 OK, no issues.

Immediately after that, the actual POST request is sent.

For the POST request, the browser does not receive any response, because it first shows the Windows Authentication popup and waits for credentials. But I don’t want to authenticate using the popup, because I'm already sending a valid JWT token in the Authorization header.

Here is the header from that POST request:

Request URL: http://localhost:60604/api/user/domainuser
Method: POST
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUz...
Content-Type: application/json;charset=UTF-8
Accept: application/json, text/plain, */*
Referer: http://localhost:55599/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

So the request does contain a token, but IIS/Windows Authentication is still being triggered and blocks the request before it reaches my controller or my custom JWT validation.

3
  • 1
    Please verify that all requests contain valid Windows authentication headers as that’s required. You will be prompted if the header is missing or contain an invalid/expired token. Commented Oct 17 at 18:32
  • Thank you for comment! I edit question and put addition about request header. Commented Oct 20 at 14:59
  • Now the cause is very clear that Windows authentication header is lost and only JWT (Bearer) presents and then the prompt becomes a must. People need very complex setups to get "either Windows or JWT" working together, so your "both Windows and JWT" approach won't be any simpler. Commented Oct 21 at 8:19

1 Answer 1

0

I think I’ve found a solution, and I’d appreciate it if someone could take a look and comment, so I know if I’m on the right track.

After numerous changes, I realized that one of the bigger problems was that I wasn’t performing a Clean + Rebuild, so Visual Studio kept caching my modifications.

In the end, the solution came down to the following part of the web.config file:

<system.web>
  <authentication mode="Windows" />
  <compilation debug="true" targetFramework="4.5.2" />
  <httpRuntime targetFramework="4.5.2" />
  <httpModules>
    <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
  </httpModules>
</system.web>

<!-- Set Windows Auth for api/auth/token endpoint -->
<location path="api/auth/token">
  <system.webServer>
    <security>
      <authentication>
        <anonymousAuthentication enabled="false" />
        <windowsAuthentication enabled="true" />
      </authentication>
    </security>
  </system.webServer>
</location>

<!-- For the rest of the app, allow anonymous auth -->
<system.webServer>
  <security>
    <authentication>
      <anonymousAuthentication enabled="true" />
      <windowsAuthentication enabled="false" />
    </authentication>
  </security>
</system.webServer>

Now, the first endpoint passes through Windows Authentication (receives the Authorization: Negotiate ... header), while the rest of the application is authorized through CustomAuthorization using JWT tokens.

Additionally, I had to configure the following in the applicationhost.config file:

<section name="anonymousAuthentication" overrideModeDefault="Allow" />
<section name="windowsAuthentication" overrideModeDefault="Allow" />

I would appreciate it if someone could review this and provide advice or recommendations on whether this setup is acceptable.

Thank you!

Sign up to request clarification or add additional context in comments.

1 Comment

you might want to consider what happens when/if you refresh the JWT. (you should re-authenticate at that point) Why the need for the JWT here?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.