Skip to content

Instantly share code, notes, and snippets.

@sir-dunxalot
Last active August 22, 2022 12:17
Show Gist options
  • Save sir-dunxalot/8b8539a0baf4e76490991c3cd4c4401d to your computer and use it in GitHub Desktop.
Save sir-dunxalot/8b8539a0baf4e76490991c3cd4c4401d to your computer and use it in GitHub Desktop.
An example of Cypress, Auth0, and Next.js authentication for a local Cypress test

Edit:

Since writing this gist, sir-dunxalot/cypress-nextjs-auth0 was released, which encapsulates this gist in a more user-friendly way. Try it out:

yarn add cypress-nextjs-auth0 --dev

This gist

A walkthrough is covered in this blog post.

  • You need to enable the password grant type in your Auth0 application's settings
  • You need to set the default directory (in your Auth0 tenant settings) to Username-Password-Authentication, which is usually the name of the database connection you want to use for password grant authentication (the name will be shown in Auth0 Dashboard --> Connections --> Database).
  • The username and password combination should be a real user (albeit one you create for testing only)
  • This method skips token verification and reveals secrets, but I am assuming I can reduce security in my test environment
  • Auth0 recommends you use seperate tenants for development, testing, and production
  • If this setup fails, you may need to add "chromeWebSecurity": false to your cypress.json config file.
import auth0 from 'auth0-js';
import Iron from '@hapi/iron';
const auth = new auth0.WebAuth({
domain: Cypress.env('auth0Domain'),
clientID: Cypress.env('auth0ClientId'),
});
Cypress.Commands.add('getUserInfo', (accessToken) => {
return new Cypress.Promise((resolve, reject) => {
auth.client.userInfo(accessToken, (err, user) => {
if (err) {
reject(err);
}
resolve(user);
});
});
});
Cypress.Commands.add('_loginTestUser', (options = {}) => {
return new Cypress.Promise((resolve, reject) => {
auth.client.loginWithDefaultDirectory({
username: Cypress.env('auth0Username'),
password: Cypress.env('auth0Password'),
audience: Cypress.env('auth0Audience'),
scope: Cypress.env('auth0Scope'),
client_secret: Cypress.env('auth0ClientSecret'),
}, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response);
}
});
});
});
Cypress.Commands.add('seal', (thingToEncrypt) => {
return new Cypress.Promise((resolve, reject) => {
try {
Iron.seal(thingToEncrypt, Cypress.env('auth0CookieSecret'), Iron.defaults).then((encryptedThing) => {
resolve(encryptedThing);
});
} catch(error) {
reject(error);
}
});
});
Cypress.Commands.add('login', (overrides = {}) => {
// cy.clearCookies(); // If needed
/* https://github.com/auth0/nextjs-auth0/blob/master/src/handlers/login.ts#L70 */
cy.setCookie('a0:state', 'some-random-state');
cy._loginTestUser().then((response) => {
const {
accessToken,
expiresIn,
idToken,
scope,
tokenType,
} = response;
cy.getUserInfo(accessToken).then((user) => {
/* https://github.com/auth0/nextjs-auth0/blob/master/src/handlers/callback.ts#L44 */
/* https://github.com/auth0/nextjs-auth0/blob/master/src/handlers/callback.ts#L47 */
/* https://github.com/auth0/nextjs-auth0/blob/master/src/session/cookie-store/index.ts#L57 */
const persistedSession = {
user,
idToken,
accessToken,
accessTokenScope: scope,
accessTokenExpiresAt: Date.now() + expiresIn,
createdAt: Date.now(),
};
/* https://github.com/auth0/nextjs-auth0/blob/master/src/session/cookie-store/index.ts#L73 */
cy.seal(persistedSession).then((encryptedSession) => {
cy.setCookie('a0:session', encryptedSession);
});
});
});
});
{
"auth0Domain": "YOUR_APP.auth0.com",
"auth0Audience": "https://YOUR_APP.auth0.com/api/v2/",
"auth0Username": "A_REAL_USERNAME",
"auth0Password": "THE_REAL_USERS_PASSWORD",
"auth0Scope": "openid profile email",
"auth0ClientId": "YOUR_CLIENT_ID",
"auth0ClientSecret": "YOUR_CLIENT_SECRET",
"auth0CookieSecret": "YOUR_COOKIE_SECRET",
}
context('Login', () => {
it('should successfully log into our app', () => {
cy.login().then((resp) => {
// User is now logged in similar to https://github.com/auth0/nextjs-auth0
});
});
});
@dchoigt
Copy link

dchoigt commented Apr 3, 2022

@sir-dunxalot thank you so much for making this. I do have one more question though. I am using the @auth0/auth0-react package which uses the Auth0Provider. This seems to be have a unique name for the cookie being created so although your code does authenticate and creates a session I'm still getting redirected. I was wondering if you knew what the cookie name should be as well as anything else that may be needed.

@maxch1414
Copy link

I have the same issue as @dchoigt

Copy link

ghost commented Aug 22, 2022

@sir-dunxalot I have a question about "Default directory" - in my company we have it setup differently. Where in the cypress code and how that is used? How can I change code to use value from that field?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment