RequestSecurityToken przy użyciu poświadczeń systemu Windows i .IF 4.5 WIF

Czy ktoś może wskazać przykładowy kod do aktywnego wystawiania RequestSecurityToken przy użyciu poświadczeń NTThread.CurrentPrincipal as ClaimsPrincipal?

Scenariusz to aplikacja internetowa asp.net z włączonym uwierzytelnianiem systemu Windows (dlatego istnieje uwierzytelniona identyfikacja WindowsIdentity). Pragnę aktywnie wywoływać STS, a nie włączać passiveRedirect, i robić to za pomocą bibliotek tożsamości .Net 4.5.

Większość próbek kodu, takich jakPomocnik roszczeń dla systemu Windows Phone lubKorzystanie z Active STS ustaw poświadczenia za pomocą nazwy użytkownika / pwd input i UserNameWSTrustBinding.

Myślałem, że rozwiązanie może obejmować podszywanie się lub dzwonienie dochannelFactory.CreateChannelWithActAsToken() z tokenem utworzonym z tożsamości systemu Windows.

- Poniższy kod .Net4.5 pobiera GenericXmlSecurityToken podczas naciskania punktu końcowego / adfs / services / trust / 13 / windowsmixed. Roszczenia dotyczą jednak konta domeny, na którym działa witryna, a nie konta domeny uwierzytelnionego użytkownika. Kiedy przełączam punkt końcowy na / adfs / services / trust / 13 / kerberossmixed, otrzymuję „nie mogę negocjować” błędów, co zostało udokumentowane w kilku pytaniach i forach, ale nie mogę zastosować żadnych oferowanych rozwiązań z .Net 4.5. Jedną z klas nie przenoszonych z Microsoft.IdentityModel jest KerberosWSTrustBinding ...

public static void CallSts()
{
    try
    {
        var wsMod = FederatedAuthentication.WSFederationAuthenticationModule;
        var appliesToEp = new EndpointReference(wsMod.Realm);
        var stsEp = new EndpointAddress(new Uri(wsMod.Issuer), EndpointIdentity.CreateSpnIdentity("stsSpn"));

        var msgBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential, false);
        msgBinding.Security.Message.EstablishSecurityContext = false;
        msgBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

        using(var factory = new WSTrustChannelFactory(msgBinding, stsEp))
        {
            factory.Credentials.SupportInteractive = false;
            factory.TrustVersion = TrustVersion.WSTrust13;

            var myRst = new RequestSecurityToken
            {
                RequestType = RequestTypes.Issue,
                AppliesTo = appliesToEp,
                KeyType = KeyTypes.Bearer,
            };
                var channel = factory.CreateChannel();
                var stsToken = channel.Issue(myRst) as GenericXmlSecurityToken;

                if(stsToken != null)
                {
                    Log.DebugFormat("Reply Token is {0}", stsToken.GetType().Name);

                    var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
                    var token = handlers.ReadToken(new XmlTextReader(new StringReader(stsToken.TokenXml.OuterXml)));
                    var identity = handlers.ValidateToken(token).First();
                    //TODO write to session
                }
                else
                {
                    Log.Debug("Reply Token is null.");
                }
        }
    }
    catch(Exception ex)
    {
        Log.Error("Rst.Call has failed", ex);
    }
}

W przypadku sugestii @leastprivilege dodam ten kod:

    var user = Thread.CurrentPrincipal as ClaimsPrincipal;
var winId = user.Identity as WindowsIdentity;
if(winId != null)
{
    // shows my domain account after I was prompted for credentials;
    // my domain account does not exist on the client machine, so it is a true domain credential
    Log.DebugFormat("WindowsIdentity Name is {0}", winId.Name);
}
using(winId.Impersonate())
{
    // again, shows my domain account
    Log.DebugFormat("Impersonation Context {0}", WindowsIdentity.GetCurrent(true).Name);
    var channel = factory.CreateChannel();
    var stsToken = channel.Issue(myRst) as GenericXmlSecurityToken;
    // request is issued, but results in SecurityNegotiationException: The caller was not authenticated by the service.
}

Co nie powiedzie się, gdy „Dzwoniący nie został uwierzytelniony przez usługę”. Ten sam STS uwierzytelni moje konto domeny w pasywnym scenariuszu przekierowania ... więc chociaż wiem, że robię coś złego, samo konto powinno zostać rozpoznane.

Aktualizacja:

Otrzymałem powiadomienie, że to pytanie otrzymało znaczną liczbę wyświetleń, więc zaproponuję następujące rozwiązanie: Chociaż skonfigurowaliśmy nasze serwery do delegowania (jak sugerował Dominick poniżej), nadal nie pokonaliśmy problemu podwójnego przeskoku. Jeśli pamiętam, utrudniliśmy nam proste zasady zarządzania siecią ponad naszą lokalną infrastrukturą informatyczną, na które może natrafić każde przedsiębiorstwo. Tak więc, podszywanie się pod podwójnym przeskokiem na serwerze z uwierzytelnianiem Windows jest niedozwolone, poświadczenia można personifikować za pomocą podwójnego przeskoku przy użyciu uwierzytelniania podstawowego. Może to być lub nie być akceptowalna sytuacja (intranet w naszym przypadku). Jeśli to zrobisz, dodałbyś

msgBinding.Security.Message.NegotiateServiceCredential = true;

do powyższej konfiguracji ChannelBinding.

questionAnswers(1)

yourAnswerToTheQuestion