web-dev-qa-db-ja.com

SPAのWeb APIでActive Directoryを使用する

1ページのアプリケーションを構築していますが、ユーザーのIDを知りたいのですが。イントラネットにはActive Directoryがありますが、それについてはあまり知りません。このようなコードを使用して、ユーザー名とパスワードを確認できます。

using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
  bool isValid = pc.ValidateCredentials("myuser", "mypassword");
}

実際、これがActive Directory側で必要なすべてです。したがって、このコードを使用してAuthorizationFilterを作成できますが、これは、すべての要求にユーザー名とパスワードが含まれている必要があることを意味します。ユーザー名とパスワードを1回だけ送信してから、認証にトークンを使用します。したがって、サーバー側アプリケーション内にトークンプロバイダーが必要です。

最新の.netテクノロジーを使用できるように、このアプリケーションをゼロから構築しています。トークン、Cookie、OAuthを処理するOwinミドルウェアがいくつかあることに気付きました。それらの何かが私を助けてくれますか?

16
Lukas Pirkl

まったく異なるものを探していたところ、CodePlexでこの素晴らしいプロジェクトを見つけました: https://angularapp.codeplex.com/ これはまさに私が探していたものです。

更新:

このアプリで役立ったのはDomainUserLoginProviderです。

public class DomanUserLoginProvider : ILoginProvider
{
    public bool ValidateCredentials(string userName, string password, out ClaimsIdentity identity)
    {
        using (var pc = new PrincipalContext(ContextType.Domain, _domain))
        {
            bool isValid = pc.ValidateCredentials(userName, password);
            if (isValid)
            {
                identity = new ClaimsIdentity(Startup.OAuthOptions.AuthenticationType);
                identity.AddClaim(new Claim(ClaimTypes.Name, userName));
            }
            else
            {
                identity = null;
            }

            return isValid;
        }
    }

    public DomanUserLoginProvider(string domain)
    {
        _domain = domain;
    }

    private readonly string _domain;
}

LoginProviderは、資格情報を確認するためのAccountControllerのアクションで使用されます。ここでAccessTokenも作成されます。

[HttpPost, Route("Token")]
public IHttpActionResult Token(LoginViewModel login)
{
    ClaimsIdentity identity;

    if (!_loginProvider.ValidateCredentials(login.UserName, login.Password, out identity))
    {
        return BadRequest("Incorrect user or password");
    }

    var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
    var currentUtc = new SystemClock().UtcNow;
    ticket.Properties.IssuedUtc = currentUtc;
    ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));

    return Ok(new LoginAccessViewModel
    {
        UserName = login.UserName,
        AccessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket)
    });
}

最後に重要なことですが、正しいミドルウェアをOwinパイプラインに追加します。

public partial class Startup
{
    static Startup()
    {
        OAuthOptions = new OAuthAuthorizationServerOptions();
    }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static void ConfigureAuth(IAppBuilder app)
    {
        app.UseOAuthBearerTokens(OAuthOptions);
    }
}

クライアント側では、認証情報を含むリクエストをAccountControllerのTokenアクションに送信するだけで、認証トークンを取得できます。このトークンをブラウザーに保存し( "Remember me"機能)、Angularの$ httpサービスを設定して、各リクエストにトークンを添付します。

services.factory('$auth', ['$q', '$http', '$path', function ($q, $http, $path) {       
    var tokenUrl = $path('api/Account/Token');

    function setupAuth(accessToken, remember) {
        var header = 'Bearer ' + accessToken;
        delete $http.defaults.headers.common['Authorization'];
        $http.defaults.headers.common['Authorization'] = header;
        sessionStorage['accessToken'] = accessToken;
        if (remember) {
            localStorage['accessToken'] = accessToken;
        }
        return header;
    }

    var self = {};

    self.login = function(user, passw, rememberMe) {
        var deferred = $q.defer();
        $http.post(tokenUrl, { userName: user, password: passw })
            .success(function (data) {
                var header = setupAuth(data.accessToken, rememberMe);
                deferred.resolve({
                    userName: data.userName,
                    Authorization: header
                });
            })
            .error(function() {
                deferred.reject();
            });

        return deferred.promise;
    };

    return self;
}]);
23
Lukas Pirkl

確かにOAuthは進むべき道ですが、古き良きフォーム認証を検討してみませんか?それは完全にシナリオに適合します-カスタムプロバイダーを使用すると、ADでユーザーを認証し、その後すべて連続するクライアント要求には、サーバー呼び出しを認証するために使用できる認証Cookieが含まれています。

このシナリオのフォームCookieは、あなたが考える「トークン」の役割を果たします。

3
Wiktor Zychla