ADFS, or Active Directory Federated Services, is Microsoft’s implementation for claims based authorization and authentication with Windows Domains. This allows companies to share or federate their security with other organizations that they trust. This is already prevalent across the web in how you can use your Facebook, Google, or Microsoft account to login to other websites because those credentials have been issued by a trusted identity provider.
When using an ADFS enabled website (called Passive authentication), the first time you access the site, it will automatically redirect to the identity provider. AFDS in this instance creates the user authenticated token and redirects the user back to the website with a cookie that you have been successfully authenticated. Subsequent calls will use the token to prove you have already been authenticated and not require the redirect to ADFS until the token is not longer valid.
The web performance tests and load tests will also need to follow the same path and authenticate to ADFS on the first call and not on subsequent calls. When you create a Web Performance Test it will succeed against ADFS because it records the ADFS authentication steps, however when you try to run it multiple times in a load test, it will fail because it no longer follows the same path because the token is already present. There are probably several ways to accomplish this but there isn’t a lot on the web for this. This solution to making the load tests work is to turn the Web Performance Test into a Coded Web Performance Test and then create a condition to check for the FedAuth cookie to decide whether or not to the user is authenticated. Here are the steps for accomplishing this.
1. Capture Test
When you create a new Web Performance Test, a web browser widow is opened with the recorder already recording. Paste the URL into the browser, display the page and any subsequent requests, and then stop the recording. This will create the set of HTTP calls. Run the test to verify that it passes.
2. Create the Coded Web Performance Test
Click on the Generate Code button and give it a name. I usually accept the default name. I also organize the Coded tests and regular ones into separate folders for better organization.
Next run the test to still make sure it works. In Visual Studio 2012, right click within the test and choose “Run Coded Web Performance Test” from the context menu. These tests will not run from the “Run Tests” option like Coded UI Tests or Unit tests.
3. Create the Load Test
Create a basic Load Test with the following settings:
- Load Pattern: Constant Load w/ 1 user
- Test Mix: Add the Coded test from step 2.
- Run Settings: Change to Test iterations and set the value to 2 iterations.
Run the test and you will see one success and one failure. You should see something like the following two errors:
- https://myserver.mydomain.com/Customers/Order/Edit/11111 Validation Rule Error ValidateResponseUrl The value of the ExpectedResponseUrl property 'https://ststest.mydomain.com/adfs/ls/auth/integrated/' does not equal the actual response URL 'https://myserver.mydomain.com/Customers/Order/Edit/11111'. QueryString parameters were ignored. - Test log
- Context parameter '$HIDDEN1.wa' not found in test context
Both of these are due to the fact that it is expecting to be redirected to the ADFS server but wasn’t because it was already authenticated.
5. Create Conditional Rule for the FedAuth cookie
To fix this, we need to create a conditional rule to check for to see if the FedAuth cookie is already present and not redirect to the ADFS server. Create the Conditional Rule before the request1 statement and add a BeginCondition call before it.
CookieExistenceRule conditionalRule1 = new CookieExistenceRule();
conditionalRule1.Webpage = "https://myserver.mydomain.com/Customers/Order/Edit/11111";
conditionalRule1.CookieName = "FedAuth";
conditionalRule1.CheckForExistence = true;
conditionalRule1.CookieDomainName = "";
conditionalRule1.CookiePath = "";
WebTestRequest request1 = new WebTestRequest("https://myserver.mydomain.com/Customers/Order/Edit/11111");
6. Add Execute Conditional Rule before the the expected result for request1
This can vary slightly based on your test. As you will see in this example, there are two places to add the ExecuteConditionRule but I had other tests where there was just one location. I also ran into instances where I needed to add an else and had to set the ExpectedResponseUrl to the correct page and not the ADFS server. This may require some trial and error before getting it correct.
request1.ExpectedResponseUrl = "https://ststest.mydomain.com/adfs/ls/auth/integrated/?wa=wsignin1.0&wtrealm=http" +
ExtractHiddenFields extractionRule1 = new ExtractHiddenFields();
extractionRule1.Required = true;
extractionRule1.HtmlDecode = true;
extractionRule1.ContextParameterName = "1";
request1.ExtractValues += new EventHandler<ExtractionEventArgs>(extractionRule1.Extract);
yield return request1;
request1 = null;
7. Add Execute Conditional Rule to any other calls where the ADFS Server is the referer.
Not all tests will have this. In this case request4 has a referer header from the ADFS server. Add the conditional rule to after the request statement. Include an else statement and set the ExpectedReponseUrl to the “default” URL when you access the site.
WebTestRequest request4 = new WebTestRequest("https://myserver.mydomain.com/");
request4.Method = "POST";
request4.ExpectedResponseUrl = "https://myserver.mydomain.com/Customers/Order/Edit/11111";
request4.Headers.Add(new WebTestRequestHeader("Referer", "https://ststest.mydomain.com/adfs/ls/auth/integrated/?wa=wsignin1.0&wtrealm=http" +
FormPostHttpBody request4Body = new FormPostHttpBody();
request4.Body = request4Body;
request4.ExpectedResponseUrl = "https://myserver.mydomain.com/leaders";
Add the EndCondition statement after the last closing bracket of the the last conditional rule. Ensure this is only called once and it is after the last conditional rule or the test will fail.
8. Rerun the Coded Web Performance Test
Repeat step 2 and rerun the Coded Web Performance Test. Verify that the test is passing.
9. Rerun the Load Test
Rerun the Load Test that you created in step 3. Both iterations should pass now. You can add more instances and/or users to test the system under load.
1. If you notice any calls to https://urs.microsoft.com/urs.asmx, this is caused by the smartscreen filter being turned on in IE. I would recommend removing these calls and disabling it in IE. This was being called multiple times within a test and taking 40+ seconds to the test.
2. If you test contains a number of AJAX calls consider turning off the think times. This can be done and the scenario step of the wizard or in the properties under scenario.