3

私は、KestrelとIISIntegrationを使用するように設定されたIdentity Server(Identity Server 4 2.0.0のASP.NET Core 2)を、launchSettings.jsonで匿名認証とWindows認証の両方を有効にして使用しています。私はまた、このようIISOptionsに構成:Windows認証で資格情報が受け入れられない

services.Configure<IISOptions>(iis => 
{ 
    iis.AutomaticAuthentication = false; 
    iis.AuthenticationDisplayName = "Windows"; 
}); 

services.AddAuthentication(); 
services.AddCors() 
     .AddMvc(); 
services.AddIdentityServer(); // with AspNetIdentity configured 

app.UseAuthentication() 
    .UseIdentityServer() 
    .UseStaticFiles() 
    .UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()) 
    .UseMvcWithDefaultRoute(); 

そして私は

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) 
    .AddOpenIdConnect(config => 
    { 
     config.Authority = "http://localhost:5000"; 
     config.RequireHttpsMetadata = false; 
     config.ClientId = "MyClientId"; 
     config.ClientSecret = "MyClientSecret"; 
     config.SaveTokens = true; 
     config.GetClaimsFromUserInfoEndpoint = true; 
    }); 

services.AddMvc(); 

のIdentity Server(IISIntegrationとケストレル上で実行して、Windowsと匿名認証が有効の両方でも、ASP.NETコア2)このクライアントを持っていますhttp://localhost:5000で、クライアントはhttp://localhost:2040で実行されています。

クライアントを起動すると、Identity Serverのログイン画面が正しく表示されますが、Windows認証をクリックすると、資格情報の入力を求められます。私は両方のアプリケーションのOutput Windowを見てきましたが、いずれの面でも例外はありません。私はIdentity ServerをIISサーバー(Windows認証を有効にし、そのプールをNETWORK SERVICEで実行している)に展開しようとしましたが、同じ動作が再現されています。

+0

あなたは' services.AddDeveloperSigningCredential()を設定しようとしたことがあり@CodeCaster:

簡単にするため、ここではユーザストアとしてIdentityを使用するように変更Windows認証が可能になりますクイックスタート・コードは、ありますか? – Kostya

+0

@KostyaKあなたが 'services.AddIdentityServer()。AddDeveloperSigningCredential()'を参照している場合、それは既に存在します。 –

+0

@CodeCaster公式のサンプルはhttps://github.com/IdentityServer/IdentityServer4.Samples/tree/から実行してみてくださいrelease/Quickstarts/6_AspNetIdentity/srcを実行して、ご使用の環境で動作するかどうかを確認してください。この方法で、問題の検索を絞り込むことができます。 – Kostya

答えて

3

私はついにそれを理解しました。私はWindows認証をサポートしていないCombined_AspNetIdentity_and_EntityFrameworkStorageクイックスタートに従った。 4_ImplicitFlowAuthenticationWithExternalから関連するコードをコピーすると、問題が修正されました。 ; `トラブルシューティング

[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public async Task<IActionResult> ExternalLogin(string provider, string returnUrl = null) 
{ 
    var props = new AuthenticationProperties() 
    { 
     RedirectUri = Url.Action("ExternalLoginCallback"), 
     Items = 
     { 
      { "returnUrl", returnUrl }, 
      { "scheme", AccountOptions.WindowsAuthenticationSchemeName } 
     } 
    }; 

    // I only care about Windows as an external provider 
    var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName); 
    if (result?.Principal is WindowsPrincipal wp) 
    { 
     var id = new ClaimsIdentity(provider); 
     id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name)); 
     id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name)); 

     await HttpContext.SignInAsync(
      IdentityServerConstants.ExternalCookieAuthenticationScheme, 
      new ClaimsPrincipal(id), 
      props); 
     return Redirect(props.RedirectUri); 
    } 
    else 
    { 
     return Challenge(AccountOptions.WindowsAuthenticationSchemeName); 
    } 
} 

[HttpGet] 
[AllowAnonymous] 
public async Task<IActionResult> ExternalLoginCallback() 
{ 
    var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); 
    if (result?.Succeeded != true) 
    { 
     throw new Exception("External authentication error"); 
    } 

    var externalUser = result.Principal; 
    var claims = externalUser.Claims.ToList(); 

    var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject); 
    if (userIdClaim == null) 
    { 
     userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier); 
    } 

    if (userIdClaim == null) 
    { 
     throw new Exception("Unknown userid"); 
    } 

    claims.Remove(userIdClaim); 
    string provider = result.Properties.Items["scheme"]; 
    string userId = userIdClaim.Value; 

    var additionalClaims = new List<Claim>(); 

    // I changed this to use Identity as a user store 
    var user = await userManager.FindByNameAsync(userId); 
    if (user == null) 
    { 
     user = new ApplicationUser 
     { 
      UserName = userId 
     }; 

     var creationResult = await userManager.CreateAsync(user); 

     if (!creationResult.Succeeded) 
     { 
      throw new Exception($"Could not create new user: {creationResult.Errors.FirstOrDefault()?.Description}"); 
     } 
    } 
    else 
    { 
     additionalClaims.AddRange(await userManager.GetClaimsAsync(user)); 
    } 

    var sid = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); 
    if (sid != null) 
    { 
     additionalClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); 
    } 

    AuthenticationProperties props = null; 
    string id_token = result.Properties.GetTokenValue("id_token"); 
    if (id_token != null) 
    { 
     props = new AuthenticationProperties(); 
     props.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = id_token } }); 
    } 

    await HttpContext.SignInAsync(user.Id, user.UserName, provider, props, additionalClaims.ToArray()); 

    await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); 

    string returnUrl = result.Properties.Items["returnUrl"]; 
    if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl)) 
    { 
     return Redirect(returnUrl); 
    } 

    return Redirect("~/"); 
} 
関連する問題