web-dev-qa-db-ja.com

Windows Active Directory認証とIDベースのクレームの使用方法

問題

Windows Active Directoryを使用して、アプリケーションに対してユーザーを認証します。ただし、Active Directoryグループを使用してコントローラー/ビューの承認を管理することは望ましくありません。

私の知る限り、ADとIDベースのクレームを結びつける簡単な方法はありません。

目標

  • ローカルActive Directoryでユーザーを認証する
  • Identityフレームワークを使用してクレームを管理する

試行(失敗)

  • Windows.Owin.Security.ActiveDirectory-Doh。これはAzure AD用です。 LDAPサポートなし。代わりに、AzureActiveDirectoryと呼ぶことはできますか?
  • Windows認証-これはNTLMまたはKeberos認証で問題ありません。問題は次から始まります:i)トークンとクレームはすべてADによって管理されており、IDクレームを使用する方法がわかりません。
  • LDAP-しかし、これらはIDクレームを使用するためにフォーム認証を手動で行うことを余儀なくされているようですか?確かにもっと簡単な方法があるはずですか?

どんな助けもありがたいです。私はこの問題に長い間立ち往生しており、この問題に関する外部からの意見に感謝します。

29
hlyates

上記のソリューションを見て、MVC6-Beta3 Identityframework7-Beta3 EntityFramework7-Beta3で機能する方向に私を押し進めました。

// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    //
    // Check for user existance in Identity Framework
    //
    ApplicationUser applicationUser = await _userManager.FindByNameAsync(model.eID);
    if (applicationUser == null)
    {
        ModelState.AddModelError("", "Invalid username");
        return View(model);
    }

    //
    // Authenticate user credentials against Active Directory
    //
    bool isAuthenticated = await Authentication.ValidateCredentialsAsync(
        _applicationSettings.Options.DomainController, 
        _applicationSettings.Options.DomainControllerSslPort, 
        model.eID, model.Password);
    if (isAuthenticated == false)
    {
        ModelState.AddModelError("", "Invalid username or password.");
        return View(model);
    }

    //
    // Signing the user step 1.
    //
    IdentityResult identityResult 
        = await _userManager.CreateAsync(
            applicationUser, 
            cancellationToken: Context.RequestAborted);

    if(identityResult != IdentityResult.Success)
    {
        foreach (IdentityError error in identityResult.Errors)
        {
            ModelState.AddModelError("", error.Description);
        }
        return View(model);
    }

    //
    // Signing the user step 2.
    //
    await _signInManager.SignInAsync(applicationUser,
        isPersistent: false,
        authenticationMethod:null,
        cancellationToken: Context.RequestAborted);

    return RedirectToLocal(returnUrl);
}
2
Will

DBに対して認証する代わりに、ユーザー名とパスワードでADを押すだけです

// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindByNameAsync(model.UserName);
        if (user != null && AuthenticateAD(model.UserName, model.Password))
        {
            await SignInAsync(user, model.RememberMe);
            return RedirectToLocal(returnUrl);
        }
        else
        {
            ModelState.AddModelError("", "Invalid username or password.");
        }
    }
    return View(model);
}

public bool AuthenticateAD(string username, string password)
{
    using(var context = new PrincipalContext(ContextType.Domain, "MYDOMAIN"))
    {
        return context.ValidateCredentials(username, password);
    }
}
20
Shoe

ASPNET5(beta6)では、アイデアはCookieAuthenticationとIdentityを使用することです:Startupクラスに追加する必要があります:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddAuthorization();
    services.AddIdentity<MyUser, MyRole>()
        .AddUserStore<MyUserStore<MyUser>>()
        .AddRoleStore<MyRoleStore<MyRole>>()
        .AddUserManager<MyUserManager>()
        .AddDefaultTokenProviders();
}

構成セクションで、以下を追加します。

private void ConfigureAuth(IApplicationBuilder app)
{
    // Use Microsoft.AspNet.Identity & Cookie authentication
    app.UseIdentity();
    app.UseCookieAuthentication(options =>
    {
        options.AutomaticAuthentication = true;
        options.LoginPath = new PathString("/App/Login");
    });
}

次に、以下を実装する必要があります。

Microsoft.AspNet.Identity.IUserStore
Microsoft.AspNet.Identity.IRoleStore
Microsoft.AspNet.Identity.IUserClaimsPrincipalFactory

拡張/オーバーライド:

Microsoft.AspNet.Identity.UserManager
Microsoft.AspNet.Identity.SignInManager

実際に、これを行う方法を示すサンプルプロジェクトをセットアップしました。 GitHubリンク

Beta8でテストし、いくつかの小さなアダプター(Context => HttpContextなど)でも動作しました。

4
jesblit

ClaimTransformationを使用できます。今日の午後、以下の記事とコードを使用して動作するようになりました。ウィンドウ認証を使用してアプリケーションにアクセスし、SQLデータベースに格納されている権限に基づいてクレームを追加しています。これはあなたを助けるべき良い記事です。

https://github.com/aspnet/Security/issues/86

要約すれば ...

services.AddScoped<IClaimsTransformer, ClaimsTransformer>();

app.UseClaimsTransformation(async (context) =>
{
IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return await transformer.TransformAsync(context);
});

public class ClaimsTransformer : IClaimsTransformer
    {
        private readonly DbContext _context;

        public ClaimsTransformer(DbContext dbContext)
        {
            _context = dbContext;
        }
        public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
        {

            System.Security.Principal.WindowsIdentity windowsIdentity = null;

            foreach (var i in context.Principal.Identities)
            {
                //windows token
                if (i.GetType() == typeof(System.Security.Principal.WindowsIdentity))
                {
                    windowsIdentity = (System.Security.Principal.WindowsIdentity)i;
                }
            }

            if (windowsIdentity != null)
            {
                //find user in database by username
                var username = windowsIdentity.Name.Remove(0, 6);
                var appUser = _context.User.FirstOrDefault(m => m.Username == username);

                if (appUser != null)
                {

                    ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Id", Convert.ToString(appUser.Id)));

                    /*//add all claims from security profile
                    foreach (var p in appUser.Id)
                    {
                        ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(p.Permission, "true"));
                    }*/

                }

            }
            return await System.Threading.Tasks.Task.FromResult(context.Principal);
        }
    }
3
K7Buoy

カスタム_System.Web.Security.MembershipProvider_を実装する方法を知っていますか?これをSystem.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials()と組み合わせて(ValidateUserをオーバーライド)使用して、Active Directoryに対して認証することができるはずです。

試してください:var pc = new PrincipalContext(ContextType.Domain, "example.com", "DC=example,DC=com"); pc.ValidateCredentials(username, password);

1
rybl