How to use Azure AD Single sign on with Cypress
At my current assignment we recently introduced Azure active directory based single sign on(SSO). Since we are building a React app we were able to leverage the react-adal library and implementing SSO on the front-end side was a matter of hours instead of days.
This however did pose a challenge for our end-to-end tests. We aim to perform a cycle that is as complete as possible in our end-to-end tests and decided that a valid JWT token and its validation should also be part of that suite. Cypress is our end-to-end testing tool and this offers a recipe for testing applications that use single sign on. Unfortunately this recipe didn’t provide us with a working solution, mainly because the (react-)adal library utilizes cross origin iframes for (re-) authentication. Cypress also runs the application under test in an iframe so we cannot leverage the existing iframe detection offered by react-adal.
Tackling the challenge
Our solution involves 2 components: a slightly adjusted runWithAdal function and a Cypress utility that mimics the behaviour of the (react-)adal library.
The adjusted runWithAdal function
This is what the runWithAdal originally looks like:
The original runwithadal method checks whether it is running in an iframe and doesn’t start react when it is. We loosen this restriction to also run inside a frame that contains the Cypress global.
The second check is whether there is an authenticated user. Since we only request an access token and not an identity token we cannot mimic the presence of an authenticated user token. We loosen this check once again by also allowing the presence of a Cypress global.
This results in the following runWithAdal function:
Cypress utility for mimicking react-adal
Now in order to obtain the access token we use the client id and client secret. We make sure the client id and secret aren’t hard coded into our tests by reading it from environment variables using Cypress.env. This way we can have our CI environment provision the id and secret without exposing it to developers. Using cy.request we perform the call to the token API and we store the resulting token via the adal authentication context API so it can pick it up when the application starts.
The adalCofig file imported at the top of the utility is the same config as the one you are using in your web application project, so it should look something like:
With a few slight adjustments you can keep using your end to end tests and test the handling of authorization in your application while you run them. The login utility mimics the behaviour of the react adal library as close as possible so your web application runs the same as in production.