简体   繁体   中英

Active auth scenario. How to issue token on home/resource ADFS using token from partner/users ADFS

Using this approach I can get auth token for my application on home/resource ADFS as well as on partner/users. Also I have claims aware WCF service of my own. It's configured to work with home/resource ADFS. Naturally, it accepts tokens from home/resource ADFS and rejects from partner/users ADFS.

I can make my WCF service trust tokens issued by partner/users ADFS but it seems wrong from architectural point of view. Somehow I should get token from home/resource ADFS using established trust between home/resource ADFS and partner/users ADFS.

Therefore I have to either 1) issue token on home/resource ADFS using token from partner/users ADFS or 2) somehow authorize user from partner/users AD directly on home/resource ADFS using his login and password. Only active authentication scenarios are considered.

Could you help me with samples of code to solve the first or/and the second problem?

I've been looking for solution for two weeks and finally found the answer. Correct flow is the flow number 1 where you authorize partner's user against partner's ADFS and then use received token to authorize it against resource ADFS. The working code sample is following

using System;
using System.IdentityModel.Tokens;
using System.ServiceModel;
using System.ServiceModel.Security;
using Microsoft.IdentityModel.Protocols.WSTrust;
using WSTrustChannel = Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannel;
using WSTrustChannelFactory = Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory;

namespace SOS.Tools.AdfsConnectionChecker
{

    /// <summary> Parameters to get token from partner's ADFS 
    /// using his domain user credentials </summary>
    public class AdfsIdentityProviderTokenRequest
    {
        /// <summary>Domain user from identity provider domain. 
        /// E.g. Name.FamalyName@ipDomainName.local or ipDomain2kName\Name.FamalyName </summary>
        public string IpDomainUserName { get; set; }
        /// <summary>Domain user password</summary>
        public string IpDomainUserPassword { get; set; }
        /// <summary> Identyty provider  token issuer server, i.e your partner adfs server. 
        /// E.g. adfs.partnerdomain.com</summary>
        public string IpTokenIssuerServer { get; set; }
        /// <summary>Resources token issuer server, i.e. your company adsf server.
        /// E.g. adfs.resourcedomain.com</summary>
        public string ResourcesTokenIssuerServer { get; set; }

    }

    /// <summary> Parameters to get token for your application  from resource ADFS 
    /// using token from partner's ADFS</summary>
    public class AdfsResourceProviderTokenForAppRequest
    {
        /// <summary>Token recieved from identity provider. </summary>
        public SecurityToken IpToken { get; set; }
        /// <summary>Resources token issuer server, i.e. your company adsf server.
        /// E.g. adfs.resourcedomain.com</summary>
        public string ResourcesTokenIssuerServer { get; set; }
        /// <summary>Apllication you want token for. In terms of ADFS its Relying Party.
        /// E.g. https://myAppServer.MyAppDomain.com/MyWcfService1 </summary>
        public string AppUrl { get; set; }

    }

    public class AdfsTokenFactory
    {

        public SecurityToken GetIpToken(AdfsIdentityProviderTokenRequest request)
        {

            //string username, string password, string tokenIssuer, string appliesTo, out 

            var binding = new WS2007HttpBinding();
            binding.Security.Message.EstablishSecurityContext = false;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
            binding.Security.Mode = SecurityMode.TransportWithMessageCredential;


            var tokenIssuerUrlFormat = "https://{0}/adfs/services/trust/13/usernamemixed";
            var tokenIssuerUrl = string.Format(tokenIssuerUrlFormat, request.IpTokenIssuerServer);


            using (var factory = new WSTrustChannelFactory(binding, new EndpointAddress(tokenIssuerUrl)))
            {
                factory.TrustVersion = TrustVersion.WSTrust13;
                factory.Credentials.UserName.UserName = request.IpDomainUserName;
                factory.Credentials.UserName.Password = request.IpDomainUserPassword;

                factory.ConfigureChannelFactory();


                var trustUrlFromat = "http://{0}/adfs/services/trust";
                var trustUrl = string.Format(trustUrlFromat, request.ResourcesTokenIssuerServer);

                var requestToken = new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue);
                requestToken.AppliesTo = new EndpointAddress(trustUrl);

                var tokenClient = (WSTrustChannel) factory.CreateChannel();
                RequestSecurityTokenResponse rsts;
                var token = tokenClient.Issue(requestToken, out rsts);
                return token;
            }

        }


        public  SecurityToken GetResourceTokenForApp(AdfsResourceProviderTokenForAppRequest request)
        {
            var binding = new WS2007FederationHttpBinding();
            binding.Security.Message.IssuedKeyType = SecurityKeyType.SymmetricKey;
            binding.Security.Message.EstablishSecurityContext = false;
            binding.Security.Mode = WSFederationHttpSecurityMode.TransportWithMessageCredential;

            var tokenIssuerUrlFormat = "https://{0}/adfs/services/trust/13/IssuedTokenMixedSymmetricBasic256";
            var tokenIssuerUrl = string.Format(tokenIssuerUrlFormat, request.ResourcesTokenIssuerServer);
            using (var factory = new WSTrustChannelFactory(binding, new EndpointAddress(new Uri(tokenIssuerUrl))))
            {
                var rst = new RequestSecurityToken
                {
                    RequestType = WSTrust13Constants.RequestTypes.Issue,
                    AppliesTo = new EndpointAddress(request.AppUrl),
                    KeyType = WSTrust13Constants.KeyTypes.Symmetric,
                };
                factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
                factory.TrustVersion = TrustVersion.WSTrust13;
                factory.Credentials.SupportInteractive = false;
                factory.ConfigureChannelFactory();


                var channel = factory.CreateChannelWithIssuedToken(request.IpToken);
                RequestSecurityTokenResponse rstr;
                SecurityToken token = channel.Issue(rst, out rstr);
                return token;
            }
        }
    }
}

You call it like this

        var factory = new AdfsTokenFactory();
        var ipTokenRequest = new AdfsIdentityProviderTokenRequest
        {
            //or "ipDomain2kName\Name.FamalyName"
            IpDomainUserName = "Name.FamalyName@ipDomainName.local", 
            IpDomainUserPassword = "userDomainPassword",
            IpTokenIssuerServer = "adfs.partnerdomain.com",
            ResourcesTokenIssuerServer = "adfs.resourcedomain.com" 
        };
        var ipToken = factory.GetIpToken(ipTokenRequest);

        var appTokenRequest = new AdfsResourceProviderTokenForAppRequest
        {
            IpToken = ipToken,
            ResourcesTokenIssuerServer ="adfs.resourcedomain.com",
            AppUrl = "https://myAppServer.MyAppDomain.com/MyWcfService1"
        };
        var appToken =  factory.GetResourceTokenForApp(appTokenRequest);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM