以编程方式完成ADFS登录



我需要在代码中执行一个完整的AFDS登录操作。我无法将用户重定向到ADFS登录页面。用户已经使用自定义身份验证机制进行了身份验证,我使用相同的凭据向ADFS进行身份验证,这是为了向SAP EP启用SSO。

我可以成功地从ADFS中检索SAML令牌,但SAP显然只能处理开箱即用的身份验证。因此,我需要对整个会话进行身份验证。

这就是我现在拥有的:

检索令牌:

            var binding = new WS2007HttpBinding();
            binding.Security.Message.EstablishSecurityContext = false;
            binding.Security.Message.NegotiateServiceCredential = false;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
            binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
            var trustChannelFactory = new WSTrustChannelFactory(binding, new EndpointAddress(AppSettings.AdfsUrl));
            trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
            trustChannelFactory.Credentials.UserName.UserName = user.UserName;
            trustChannelFactory.Credentials.UserName.Password = PasswordService.Decrypt(user.UserPassword, user.UserID.ToString(CultureInfo.InvariantCulture));
            trustChannelFactory.ConfigureChannelFactory();
            // Create issuance issuance and get security token
            var requestToken = new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue);
            requestToken.AppliesTo = new EndpointAddress(AppSettings.ServicePortalUrl);
            requestToken.KeyType = WSTrust13Constants.KeyTypes.Bearer;
            var tokenClient = (WSTrustChannel) trustChannelFactory.CreateChannel();
            var token = tokenClient.Issue(requestToken) as GenericXmlSecurityToken;
            return token;

尝试获取声明,以便在重定向到SAP门户之前,将用户主体放在HttpContext中。(长镜头)

        var tokenHandlers = new SecurityTokenHandlerCollection(new SecurityTokenHandler[] { new SamlSecurityTokenHandler() });
        tokenHandlers.First().Configuration.AudienceRestriction.AudienceMode = AudienceUriMode.Never;
        tokenHandlers.First().Configuration.CertificateValidationMode = X509CertificateValidationMode.None;
        tokenHandlers.Configuration.CertificateValidationMode = X509CertificateValidationMode.None;
        var trusted = new TrustedIssuerNameRegistry("*.domain.com");
        tokenHandlers.Configuration.IssuerNameRegistry = trusted;
        var samlToken = tokenHandlers.ReadToken(new XmlTextReader(new StringReader(token.TokenXml.OuterXml)));
        var claimsPrincipal = new ClaimsPrincipal(tokenHandlers.ValidateToken(samlToken).First());
        HttpContext.Current.User = claimsPrincipal;     

这不起作用,因为我不断收到X509证书验证错误。

我尝试过的:

  • 提供SAML签名作为MYSAPSSO2令牌(可能性很小,不起作用)
  • 将用户主体放在HTTP上下文中,正如我所看到的,SAP在HTTP上下文中将查找IPrincipal。(无法使其工作)
  • 设置MSISAuthenticated cookie,但不知道如何获取值(身份验证时刻的base64时间戳?)

我有什么明显的监督方式吗?基本上,我只想执行与ADFS登录页面相同的身份验证,但在代码中,这样用户就不会看到第二个登录页面。

这样试试。。。

            // ######################### TOKEN HANDLER ########################################################################################################################
            var genericToken = token as GenericXmlSecurityToken;
            var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlerCollectionManager.SecurityTokenHandlerCollections.First();
            // ######################## HANDLE AudienceRestriction programatically.############################################################################################
            //handlers.Configuration.AudienceRestriction.AudienceMode.Equals(0);
            handlers.Configuration.AudienceRestriction.AllowedAudienceUris.Add(new Uri (svcEndpoint)); // porgramatically validate AllowedAudienceUris. This is your RP. https://learn.microsoft.com/en-us/dotnet/api/system.identitymodel.selectors.audienceurimode?view=netframework-4.8#fields
            // ##### HANDLE STS SIGNING CERTIFICATE VALIDATIONS. Set to none for ADFS autocertificaterollover.
            handlers.Configuration.CertificateValidationMode = X509CertificateValidationMode.None; //Also set in App.config / web.config 
            // ########################## HANDLE IssuerNameRegistry automatically.##############################################################################################
            
            // ######################## READ METADATA OF ADFS TO EXTRACT SIGNING CERTIFICATE ###################################################################################
            AdfsMetadataService svc = new AdfsMetadataLoader("https://" + opts.Farmname +  "/FederationMetadata/2007-06/FederationMetadata.xml");
            var metadata = svc.Get();
            string IdP = metadata.Result.Identity;
            string stringSigningCert = metadata.Result.SigningCertificateString;
            // ####################### CONVERT FROM BASE64 TO READ SIGNING CERTIFICATE THUMBPRINT AND SUBJECT TO USE IN ISSUERNAMEREGISTRY #####################################
            byte[] bytes = Convert.FromBase64String(stringSigningCert);
            var AdfsSigncert = new X509Certificate2(bytes);
            //Console.WriteLine(IdP +  stringSigningCert + cert.Thumbprint + cert.Subject);
            var registry = new ConfigurationBasedIssuerNameRegistry();
            registry.AddTrustedIssuer(AdfsSigncert.Thumbprint, AdfsSigncert.Subject);
            handlers.Configuration.IssuerNameRegistry = registry;
            var cToken = handlers.ReadToken(new XmlTextReader(new StringReader(genericToken.TokenXml.OuterXml)));
            var identity = handlers.ValidateToken(cToken).First();
            var userIdenity = new ClaimsPrincipal(identity);
            Console.WriteLine("Successfully Authenticated with identity type userIdenity.Identity.Name with value ~~~ " + userIdenity.Identity.Name);
            foreach (var c in userIdenity.Claims)
            {
                Console.WriteLine("Claim Type = " + c.Type + " ~~~ Claim Value = " + c.Value);   
            }

最新更新