ADFS 2.0 supports multiple authentication methods through authentication handlers that are mutually exclusive. If one of the handlers runs, the others don’t. There is no way to implement a fallback logic if one the handlers fail to run or the user was not able to provide the expected credentials, so supporting dual authentication such as username/password and client certificates is sometimes problematic. The following list shows the handlers included out of the box with ADFS 2.0,
1 2 3 4 5 6 7 8
Those handlers are for Forms Authentication (Username/Password in an html form), Integrated Windows Authentication, Client Cert Authentication, and finally Http Basic Auth Authentication. The order in this list determines the priority by default unless the priority has been changed in the execution context. The order in the execution context can be changed in multiple ways. For example, when you are doing WS-Federation, the relying party can pass an additional “WAuth” query string parameter with the expected authentication type such as “urn:oasis:names:tc:SAML:1.0:am:password” for Forms Authentication or “urn:ietf:rfc:2246” for Client Cert authentication, which overrides the priority in the list set on the configuration. The same thing can be done for SAML 2.0 by changing the authentication context in the SAML Request message or changing the URL.
However, as I said before, in one of the handlers run, you will not have a chance to run any of the other handlers unless you implement some workaround. For example, you might want to add a checkbox in the html form for Forms authentication to allow the user to authenticate with a client certificate. When the checkbox is clicked, you do an http redirect to ADFS but changing the URL this time to use this new authentication method. If the RP is using WS-Federation, that means a new redirect that includes the WAuth query string variable with the value “urn:ietf:rfc:2246”, or a redirect to “auth/sslclient/” in the case of SAML 2.0.
If you want to avoid this manual step and detect the client certificate automatically, more work is involved, and it is what we are going to discuss next.
- Enable Forms Authentication as default in the configuration file. The “Forms” handler must be on top of the list.
- Create a new virtual directory in the ADFS IIS, and configure that virtual directory to require HTTPS and Accept Client Certs.
- Configure an ASP.NET Generic handler in that virtual directory to check if the certificate is present or not
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
- Configure this handler in the web.config of that virtual directory.
1 2 3 4 5
1 2 3 4 5 6 7
This code is very simple. It simply does a redirect when the cert is present (the callback was called with a “true” value). The redirect in this sample is only valid for SAML 2.0
- Modify the FormsSign.aspx page to include the following code at the end of the Page_Load event,
1 2 3 4
This code injects our CertCallBack.js script in the page and it also includes the script located in the virtual directory configured to accept client certs (/CertDetection/Script invokes the ASP.NET Handler basically)
That should be all. If the browser detects a client certificate when the script in the CertDetection virtual directory is resolved, the callback will be executed with a true value, making the form to do a redirect to authenticate the client with a Client Certificate instead. Otherwise, the client will see the Form to enter the username and password. We are adding a new virtual directory for not interferring with the existing authentication methods in the ADFS virtual directory.