auth0-spa-js: Cannot automate login in cypress since 1.12 using cookie injection
Describe the problem
In order to automate test to a frontend application i’m currently working on, I’m using cypress on a react app.
As it’s not possible to navigate to the auth0 login page, I’ve been using a command that generates the user token using the API POST /oauth/token, and then inject the token in the cookies and redirect the front end as it would occur after a successful login using the state param.
But since version 1.12, the behavior has changed and the auth0 sdk does not seem to accept this way to inject authentication.
Here is the code I’m using to authenticate the browser automation (This code still works using 1.11):
Cypress.Commands.add("login", ({ username, password }, appState = { targetUrl: "/" }) => {
cy.log(`Log in as ${username}`)
cy.request({
method: "POST",
url: Cypress.env("AUTH0_GET_TOKEN_URL"),
body: {
grant_type: "password",
username: username,
password,
audience: Cypress.env("AUTH0_AUDIENCE"),
scope: "openid profile email",
client_id: Cypress.env("AUTH0_CLIENTID"),
client_secret: Cypress.env("AUTH0_CLIENT_SECRET"),
},
}).then(({ body }) => {
const { access_token, expires_in, id_token } = body
cy.server()
cy.route({
url: Cypress.env("AUTH0_GET_TOKEN_URL"),
method: "POST",
response: {
access_token,
id_token,
scope: "openid profile email",
expires_in,
token_type: "Bearer",
},
})
const stateId = "test"
cy.setCookie(
`a0.spajs.txs.${stateId}`,
encodeURIComponent(
JSON.stringify({
appState,
scope: "openid profile email",
audience: Cypress.env("AUTH0_AUDIENCE"),
redirect_uri: "http://localhost:3000",
})
)
)
cy.visit(`/?code=test-code&state=${stateId}`)
})
})
Maybe it’s a bad thing to do, but it seemed fine to me to do it that way, if you have any other option available I would be glad to hear about how I should do it differently.
What was the expected behavior?
I was expecting that the state handling would be the same after the version upgrade.
Reproduction
- Allow password authentication on your tenant
- Generate a token using auth0 api (POST https://{your-tenant}.auth0.com/oauth/token)
- insert a cookie at
a0.spajs.txs.${stateId}as the login page would do - mock the auth0 api with the generated token
- redirect your app to the login callback with the parameters
/?code=any-code&state=${stateId}
Can the behavior be reproduced using the SPA SDK Playground?
- I’m not sure about how to test it with the playground
Environment
Please provide the following:
- Version of
auth0-spa-jsused: 1.12.1 - Which browsers have you tested in? any
- Which framework are you using, if applicable (Angular, React, etc): react
- Other modules/plugins/libraries that might be involved: cypress
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 17 (7 by maintainers)
Hey @eliasplatekdkt
apologies, I just used that as an example of setting
localstorage- you don’t need to do the cookie stuffI’ve put a working example here https://github.com/adamjmcgrath/cypress-spa-example
I think it’s simpler than your solution because it doesn’t rely on cy.request/cy.server It has the disadvantage of having to change
cacheLocationin cypress mode But it works with the latest version of spa js and IMO relies less on our internals@adamjmcgrath this is a very elegant solution and it works seamlessly. I tried the same implementation but some fields were missing which is why it didn’t work. Thanks a lot for your time !
I think that would be interesting to update the documentation at https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/ which explains quite a different approach, and can be misleading for people searching for
cypress+auth0, the localStorage approach requires less setup in cypress. I’m going with this solution in my project.@eliasplatekdkt @adamjmcgrath Thank you so much guys ! It helps me a lot to auto login users on my SPA ! 💪
Thanks for sharing that @StephenCleary
If anyone else is having trouble setting up https://github.com/auth0/auth0-spa-js/issues/581#issuecomment-697323567 - It’s usually because the
localStoragekey for the credentials you’re putting in aren’t the same as the key SPA JS is looking for (eg you unexpectedly hadoffline_accessin your scopes)I added a suggestion and snippet of code that might help you debug situations like this here https://github.com/adamjmcgrath/cypress-spa-example/issues/2#issuecomment-765583180
One thing that tripped me up was I had
useRefreshTokensset totrue, so the auth0 library was addingoffline_accessto my scopes, which changes the localstorage key.Glad you got it working @vinzcelavi!
@stevehobbsdev I’ve been playing a bit with the library, and it can be fixed by removing the pre-check on the nonce in handleRedirectCalback:
This check can be removed safely I think because the nonce is revalidated after getting the token in verifyIdToken:
If the transaction test only checks for the code_verifier before calling the
POST /oauth/token, then you ensure that the code verifier is provided, and when you verify the id_token the nonce is validated as before (it is even declared as an optional parameter).From my point of view it seems enough to fix it like this, I can provide a PR if it’s okay for you
@eliasplatekdkt thanks for raising. In v1.12 we moved from using cookies for the transaction store to session storage, so if you’re relying on cookie behaviour your tests will need to be updated.
It does get slightly easier though, in that we no longer include the state value in the key name, so that can be dropped. Otherwise, the data stored inside session storage should be exactly the same as it was for cookies.
Let me know if you’re able to get this working as before.