@simulacrum/auth0-cypress
A Cypress plugin specifically created for SDK's that integrate
with Auth0! @simulacrum/auth0-cypress will simulate an auth0 server, running on localhost
, so you
don't have to create fake Auth0 accounts while developing or running tests that require authentication!
Features:
- No interaction with real Auth0 servers making any token request completely free!
- Supports multiple SDK's that integrate with Auth0!
- Create individual users for each test, each with a unique set of claims, permissions or scopes!
- Can be run in CI/CD pipelines!
- Works with the latest Cypress and Auth0 SDK versions!
Contents
Installation
Step 1: Install the addon
npm install @simulacrum/auth0-cypress --dev
Step 2: Choose which sdk or javascript sdk (default @auth0/auth0-react)
This plugin supports the following javascript sdks that interface with auth0:
To set the correct SDK, you need to set the AUTH0_SDK
environment variable inside your cypress.config.ts or through
any of the usual cypress environmental varaibles options.
in the cypress.config.ts file
export default defineConfig({
env: {
AUTH0_SDK: 'auth0-js',
}
});
or with the use of an .env
file (
examples: auth0-vue, auth0-react, nextjs-auth0
or create-react-app)
AUTH0_SDK="auth0-js"
Step 3: Import the commands
import '@simulacrum/auth0-cypress';
Step 4: Register the encrypt task in the cypress.config.ts
We need to register an encrypt cypress task.
ESM
import { encrypt } from '@simulacrum/auth0-cypress/encrypt';
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('task', { encrypt });
},
},
});
commonjs
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
const { encrypt } = require('@simulacrum/auth0-cypress/encrypt');
on('task', { encrypt });
},
},
});
Step 5: Configure Auth0
An example of all the possible environment variables can be found in the cypress.config.ts file.
NOTE: Make very sure that the values that you pass into Cypress are the EXACT same as the values you use in your
application. If you use different values, the login will be successful but the app will not be logged in or it will
redirect you to the login page.
export default defineConfig({
env: {
AUTH0_SDK: 'auth0_react',
AUTH0_SIMULATOR_PORT: 4000,
AUTH0_RUNNING_PORT: 4400,
AUTH0_AUDIENCE: 'https://thefrontside.auth0.com/api/v1/',
AUTH0_CLIENT_ID: "00000000000000000000000000000000",
AUTH0_CONNECTION: "Username-Password-Authentication",
AUTH0_SCOPE: "openid profile email offline_access",
AUTH0_CLIENT_SECRET: '6d0598f28f62a9aee14929ef46c7c8befdc015',
AUTH0_COOKIE_SECRET: "",
AUTH0_SESSION_COOKIE_NAME: "appSession",
}
});
These same variables can also be set through the use of env
files: (
examples: auth0-react, nextjs-auth0 create-react-app)
AUTH0_SDK="auth0_react"
AUTH0_RUNNING_PORT=4400
AUTH0_AUDIENCE="https://your-audience/"
AUTH0_CONNECTION="Username-Password-Authentication"
AUTH0_SCOPE="openid profile email offline_access"
AUTH0_CLIENT_ID="YOUR_AUTH0_CLIENT_ID"
AUTH0_CLIENT_SECRET='YOUR_AUTH0_CLIENT_SECRET'
AUTH0_COOKIE_SECRET='6d0598f28f62a9aee14929ef46c7c8befdc0150d870ec462fa45629511fd2a46'
How it works
Under the hood, @simulacrum/auth0-cypress
uses another package
called @simulacrum/auth0-simulator which will first
start a GraphQL interface/web server (by default on localhost:4000). This will then require a mutation command to start
the actual Auth0 simulation server which you will then use in the Cypress tests. This is what @simulacrum/auth0-cypress
will do for you, as well add various Cypress commands.
Usage with start-server-and-test
Cypress recommends using start-server-and-test to ensure the test
process exits and any servers are shut down.
Make sure to follow the following convention for creating your own start command with Auth0-Cypress
npx start-server-and-test <first command> <first resource> <second command> <second resource> <test command>
As example:
npx start-server-and-test \
'npm run start:server' http://localhost:3000 \
'npm run start:auth0' http://localhost:4000 \
cypress open
See the scripts section in package.json for various examples on the use of integrating
withstart-server-and-test
command.
Step 6: Configure your localhost to use a https connection
The Auth0 SDK's require a https connection to work. This can easily be setup by using mkcert to create a self-signed certificate for your localhost.
A running example with setting up mkcert instruction can be found here at @simulacrum/ui
The following commands are now available in your test suite:
Commands
An example of these commands in use can be found in the login.spec.ts file.
cy.createSimulation()
createSimulation
creates the fake auth0 server with your configuration
describe('tests requiring auth', () => {
it('should access restricted resource', () => {
cy.createSimulation();
cy.createSimulation({ options });
});
})
cy.given()
given
creates a fake user that can be used to log into the fake auth0 server.
create random user
describe('tests requiring auth', () => {
it('should access restricted resource', () => {
cy
.createSimulation({ options })
.given()
.login();
});
})
supply fixed fields
describe('tests requiring auth', () => {
it('should access restricted resource', () => {
cy
.createSimulation()
.given({ email: 'bob@gmail.com' })
.login();
});
})
cy.login()
Depending on the SDK that has been configured, a token will be requested through the use
of getTokenSilently().
Which will set the token in the local storage of the browser.
Call login and logout in your test. For example:
describe('log in', () => {
it('should get token without signing in', () => {
cy
.createSimulation({ options })
.visit("/")
.contains("Log out").should('not.exist')
.given()
.login()
.visit("/")
.contains("Log out")
.logout();
});
});
cy.logout()
cy.logout
will destroy the simulation and do any clean up between tests like removing cookies.
cy.logout();
Troubleshooting
When running my app in Cypress, the login is successful but the app is not logged in or it redirects me to the login page:
Make VERY sure that the Auth0 env variable values you're using, are the EXACT same as the variables you're passing into
Cypress.
Running with Vue/vite Cypress is not opened and start-server-and-test is hanging
https://github.com/bahmutov/start-server-and-test#use-http-get-requests
Debugging
It is possible to hook up express middleware to log each endpoint that is called and any associated querystring or POST
data by simply adding the debug: true
option when calling createSimulation
:
describe('debug auth0 server', () => {
it("should log in and log out", () => {
cy.createSimulation({ debug: true })
});
});