Use Windows Auth to authenticate user and then generate JWT in ASPNET Core 2.1

不羁的心 提交于 2019-12-25 00:09:02

问题


I have an ASP.NET Core 2.1 WebApi, in which I have implemented JWT authentication. The user calls api/authentication/authenticate, passes their username/password in the message body, and gets back a JWT in return which they then use to access the service.

I also need the API to accept Windows authentication -- the user will call api/authentication/windows passing no user information, the service will check they are in the list of authorized users as listed in the web.config file (if I am hosting in IIS). If so, return a JWT token and the user can use that to access the service.

Currently I'm thinking about this...

  1. The api/authentication/windows method will get the username from the request
  2. Check the username against the list of authorized users. If they are on it, return a token. If not, go to (3)
  3. Check against any groups in the authorized users list. If they are a member, return a token. If not, return a 401 Unauthorized error

Is this the correct way to approach this?

Very similar (unanswered) question here: Generate JWT token on successful authentication with Windows Authentication


回答1:


If you want to enable both JWT and AD authentication ,in my option, you still need to validate the user's credential(username/password) against Active Directory in web api :

https://www.brechtbaekelandt.net/blog/post/authenticating-against-active-directory-with-aspnet-core-2-and-managing-users

Pass just username won't work since there is no authenticated user context in web api .

After validating user credential , you can generate jwt token as usual , for example if using HS256:

private string BuildToken()
{
    var claims = new[] {
        new Claim(JwtRegisteredClaimNames.NameId,"name1"),
        new Claim(JwtRegisteredClaimNames.Sub,"name1"),
        new Claim("customer","customer1"),
        new Claim(JwtRegisteredClaimNames.Email,"wuxiyuan@sina,com"),
        new Claim("role","user"),
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Youkey"));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken("name1",
        "name1",
    claims,
    expires: DateTime.Now.AddDays(1),
    signingCredentials: creds);

    return new JwtSecurityTokenHandler().WriteToken(token);
}



回答2:


  • To get the username from the request to the route api/authentication/windows you should activate windows authentication for the asp.net core application. You can achieve that either modifying the web.config or enable the windows authentication in IIS.
   <configuration>
     <system.webServer>
       <security>
         <authentication>
           <anonymousAuthentication enabled="true" />
           <windowsAuthentication enabled="true" />
         </authentication>
       </security>
     </system.webServer>
   </configuration>
  • For debugging purposes modify launchSettings.json:
   "iisSettings": {
     "windowsAuthentication": true,
   }
  • Leave the anonymous authentication activated: <anonymousAuthentication enabled="true" />. It is necessary in order the JWT authentication works properly for the route api/authentication/authenticate

  • Make sure that the attribute forwardWindowsAuthToken of the aspNetCore element in web.config is not deactivated: forwardWindowsAuthToken="true" or remove it because of the default value (true)

  • Add IISIntegration to the webHostBuilder unless you use a default builder: WebHost.CreateDefaultBuilder(args) - UseIISIntegration is called implicit within this extension method.

  • Add an Authorize attribute for the POST-method which will be mapped with the route api/authentication/windows

  • Test the authentication (sending windows-credentials):

    var handler = new System.Net.Http.HttpClientHandler()
    {
        Credentials = System.Net.CredentialCache.DefaultCredentials
    };

    var httpClient = new System.Net.Http.HttpClient(handler)
    {
        BaseAddress = new Uri("http://localhost")
    };

    var response = await httpClient.PostAsync("api/authentication/windows", null);

or using XMLHttpRequest object:

    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://localhost/api/authentication/windows', true);
    xhr.withCredentials = true;
    xhr.send();
  • Get the user name in the controller:
    var username = HttpContext.User.FindFirst(System.Security.Claims.ClaimTypes.Name)?.Value;
  • Generate a JWT-Token, e.g using jose-jwt:
 var claims = new Dictionary<string, object>
 {
     ["jti"] = Guid.NewGuid(),
     ["sub"] = username,
     ["exp"] = DateTimeOffset.UtcNow.AddMinutes(100).ToUnixTimeSeconds()
 };

 var secretKey = new byte[] { 164, 60, 194, 0, 161 };

 var headers = new Dictionary<string, object>
 {
     ["alg"] = "HS512",
     ["typ"] = "JWT"
 };

 var token = JWT.Encode(claims, secretKey, JwsAlgorithm.HS512, headers);


来源:https://stackoverflow.com/questions/57711147/use-windows-auth-to-authenticate-user-and-then-generate-jwt-in-aspnet-core-2-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!