I need to perform a complete AFDS login action in code. I cannot redirect the user to the ADFS login page. The user has already authenticated using a custom authentication mechanism and I use the same credentials to authenticate to ADFS, this to enable SSO to a SAP EP.
I can successfully retrieve a SAML token from the ADFS but SAP apparently can only handle the out of the box authentication. So I will need to authenticate the entire session.
This is what I have right now:
Retrieve the token:
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;
And an attempt to get the claims so I could perhaps put the user principal in the HttpContext before redirecting to the SAP Portal. (Long shot)
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;
This does not work, as I keep on getting X509 certificate validation errors.
What I've tried:
- Providing the SAML signature as MYSAPSSO2 token (long shot, did not work)
- Putting the user principal in the HTTP context as I saw that SAP looks for an IPrincipal in the HTTP context. (Can't get it to work)
- Set the MSISAuthenticated cookie, but have not idea how to get the value (base64 timestamp of moment of authentication?)
Is there any obvious way that I'm overseeing? Basically, I just want to perform the same authentication the ADFS login page does, but in code, so the user doesn't see a second login page.
Try it like this ...