I have an ASP.NET web application (running on .NET 4.5). It's currently doing forms authentication. We've set up an ADFS 3 server with multiple federations, some internal, some external (customer STSs), and we'd like to configure the web application to use an active authentication model. If I understand it correctly, that means that we will continue to use the login form in my web application, and it will gather credentials from the users, then send a security token request to our ADFS server. The token request would presumably tell ADFS which federation to send the request to. If everything is successful, then I get a token back from ADFS, validate it, and construct a ClaimsPrinciple and go from there.
Now, with that background, the problem I'm running into is how to send the token request to ADFS in .NET 4.5. Every example I've seen, despite being labeled as applicable to .NET 4.5 uses the old UserNameWSTrustBinding class from WIF. This is deprecated and not present in 4.5. Web searches for "UsernameWSTrustBinding 4.5 equivalent" have been fruitless. I've seen one guy construct his own class to duplicate the functionality, but I can't believe this is necessary. I've got a hunch that there is a class here somewhere that I'm supposed to be using for the binding in the WSTrustChannelFactory, but I can't find it. Or, perhaps the entire WSTrustChannelFactory pattern is outdated as well (but then why would it have been included in .NET 4.5)?
Can anyone provide a snippet of code or even shed some light on how you're supposed to go about active authentication in .NET 4.5?
So far my best idea has been to check username in the users cookie (if it exists) or from regular login form when the cookie didn't exist. With that info, I can determine whether it needs to be sent to the IdP or not. In the case that it needs to be sent to the IdP, I can just build a request URL and redirect.
WSFederationAuthenticationModule instance = FederatedAuthentication.WSFederationAuthenticationModule;
SignInRequestMessage request = instance.CreateSignInRequest(Guid.NewGuid().ToString(), instance.Realm, true);
request.AuthenticationType = "urn:federation:authentication:windows";
Response.Redirect(request.WriteQueryString());
Of course, I can tweak that request with the appropriate .HomeRealm value or .AuthenticationType in order to skip the HRD process, and then after that, they'll be sent back to the app authenticated and with a proper claimsidentity.
One reason that this isn't the perfect answer for me is that if the user has never logged in before, or has cookies disabled, and depending on the federation, there's potential for them to have to login twice. That is, once to the app's login form, and once to the ADFS form. That's why I was hoping to be able to send a request programmatically somehow instead of redirecting. That way I could presumably send the username & password that were already collected by the app without having to collect them again at ADFS.
For that reason, I won't mark this as the answer. I'd like to hold out for better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With