我需要在代码中执行一个完整的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);
}