javascript icon indicating copy to clipboard operation
javascript copied to clipboard

HTTP 401 when Cypress chromeWebSecurity is set to false

Open karam94 opened this issue 2 years ago • 6 comments

  • [x] Review the documentation: https://docs.clerk.dev/
  • [x] Search for existing issues: https://github.com/clerkinc/javascript/issues
  • [x] Go through package changelog files.
  • [ ] Provide the Frontend API key from your application dashboard.

Package + Version

  • [ ] @clerk/clerk-js
  • [ ] @clerk/clerk-react
  • [ ] @clerk/nextjs
  • [x] @clerk/remix
  • [ ] @clerk/clerk-expo
  • [ ] @clerk/backend-core
  • [ ] @clerk/clerk-sdk-node
  • [ ] @clerk/edge
  • [ ] other:

Version:

^0.1.0-alpha.6

Browser/OS

Chrome latest

Description

I have a Remix application that uses Clerk for authentication alongside Paddle for payments. Paddle is integrated via an iframe using their JavaScript library.

With Cypress, in order to avoid cross-origin errors when running E2E tests (e.g. to write an E2E test that covers a full payment flow), it is necessary to put the below within cypress.json:

{
  "chromeWebSecurity": false
}

The above is necessary to allow me to access inputs, buttons, etc within the Paddle payment iframe.

The problem is that when I disable chromeWebSecurity, my app becomes unusable because Clerk starts throwing 401 Unauthorized errors. I understand that this is most likely a security feature enabled by Clerk, however it would be good if there was a way to turn this off for Clerk test/sandbox environments to facilitate testing? If it isn't possible or there isn't a workaround, then I'm also happy to take no as an answer as I understand security implications etc.

Thanks

karam94 avatar May 21 '22 22:05 karam94

Hello @karam94 Thanks for the report, can you please send the 401 request information ? (headers, any response etc.)

Also does this happen only by setting this option to false ? (a sandbox with a simple example would be of great help here)

igneel64 avatar May 23 '22 06:05 igneel64

Hello @karam94 Thanks for the report, can you please send the 401 request information ? (headers, any response etc.)

Also does this happen only by setting this option to false ? (a sandbox with a simple example would be of great help here)

Hi @igneel64

Will try to get you this information & an example in the next few days.

Thanks!

karam94 avatar May 27 '22 22:05 karam94

Hello @karam94 Thanks for the report, can you please send the 401 request information ? (headers, any response etc.)

Also does this happen only by setting this option to false ? (a sandbox with a simple example would be of great help here)

Hi @igneel64 Will update this with a sandbox example as soon as I have one available (very busy atm sorry). It can be recreated by simply taking the remix-auth-starter, adding Cypress tests to it and modifying the cypress.json. The remix site won't work as it's wrapped by the Clerk HOC.

However, I do have an update with headers etc you requested. So, I've upgraded @clerk/remix from ^0.1.0-alpha.6 to ^0.5.0 & this has seen a change of behaviour once I add "chromeWebSecurity": false to my cypress.json.

Instead of the 401, I now get a 400 (Bad Request). The response body looks as below:

{
  "errors": [
    {
      "message": "Invalid request",
      "long_message": "To protect against CSRF attacks, Clerk Frontend API can only be accessed when the HTTP Origin (XHR requests) or HTTP Authorization (native application or curl requests) headers are present.",
      "code": "request_header_missing"
    }
  ]
}

I understand why this security feature is in place & as expected, but as I explained, for testing purposes it might be useful to be able to disable it. Otherwise, I simply cannot e2e test payments that rely on iframes/cross origin requests.

karam94 avatar May 28 '22 22:05 karam94

Same problem here. I need test a payment flow, but with chromeWebSecurity I get 401 on xhr request.

pascencio avatar Jul 14 '22 02:07 pascencio

I enable some experimental features in cypress.config, then I think it's work

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  projectId: 'xxx',
  chromeWebSecurity: true,
  e2e: {
    experimentalModifyObstructiveThirdPartyCode: true,
    experimentalSessionAndOrigin: true,
    // ...
  }
})
Cypress.Commands.add('signIn', () => {
  cy.log('Signing in.')
  cy.visit('/sign-up')
  cy.origin(process.env.CLERK_DEV_URL, () => {
    cy.window().should((window) => {
      expect(window).to.not.have.property('Clerk', undefined)
      expect(window.Clerk.isReady()).to.eq(true)
    }).then(async (window) => {
      const res = await window.Clerk.client.signIn.create({
        strategy: 'password',
        identifier: 'xxx,
        password: 'xxx'
      })
      await window.Clerk.setActive({
        session: res.createdSessionId
      })

      cy.log('Finished Signing in.')
    })
  })
})

himself65 avatar Aug 15 '22 19:08 himself65

I enable some experimental features in cypress.config, then I think it's work

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  projectId: 'xxx',
  chromeWebSecurity: true,
  e2e: {
    experimentalModifyObstructiveThirdPartyCode: true,
    experimentalSessionAndOrigin: true,
    // ...
  }
})
Cypress.Commands.add('signIn', () => {
  cy.log('Signing in.')
  cy.visit('/sign-up')
  cy.origin(process.env.CLERK_DEV_URL, () => {
    cy.window().should((window) => {
      expect(window).to.not.have.property('Clerk', undefined)
      expect(window.Clerk.isReady()).to.eq(true)
    }).then(async (window) => {
      const res = await window.Clerk.client.signIn.create({
        strategy: 'password',
        identifier: 'xxx,
        password: 'xxx'
      })
      await window.Clerk.setActive({
        session: res.createdSessionId
      })

      cy.log('Finished Signing in.')
    })
  })
})

Thank you, I will give this a go when I can.

karam94 avatar Aug 22 '22 17:08 karam94

I enable some experimental features in cypress.config, then I think it's work

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  projectId: 'xxx',
  chromeWebSecurity: true,
  e2e: {
    experimentalModifyObstructiveThirdPartyCode: true,
    experimentalSessionAndOrigin: true,
    // ...
  }
})
Cypress.Commands.add('signIn', () => {
  cy.log('Signing in.')
  cy.visit('/sign-up')
  cy.origin(process.env.CLERK_DEV_URL, () => {
    cy.window().should((window) => {
      expect(window).to.not.have.property('Clerk', undefined)
      expect(window.Clerk.isReady()).to.eq(true)
    }).then(async (window) => {
      const res = await window.Clerk.client.signIn.create({
        strategy: 'password',
        identifier: 'xxx,
        password: 'xxx'
      })
      await window.Clerk.setActive({
        session: res.createdSessionId
      })

      cy.log('Finished Signing in.')
    })
  })
})

Your config has chromeWebSecurity set to true, you need to set it to false. Unfortunately this did not work :/

Any other workaround would be highly appreciated.

MehdiSv avatar Oct 27 '22 23:10 MehdiSv

We've just updated the instructions on how to use Clerk with Cypress. Let me know if this helps.

SokratisVidros avatar Nov 04 '22 13:11 SokratisVidros

Thanks for the answer @SokratisVidros! I went through those instructions but unfortunately they do not help with the 400.

As soon as you put chromeWebSecurity to false, Clerk stops working. It's because the origin header is not passed anymore.

MehdiSv avatar Nov 04 '22 17:11 MehdiSv

I see. The origin header is a hard requirement on our end. I will close this one for now.

SokratisVidros avatar Nov 07 '22 05:11 SokratisVidros