bjowes / cypress-ntlm-auth

Windows authentication plugin for Cypress
MIT License
54 stars 10 forks source link

Works with Cypress 3.2.0 but not 3.3.1 #51

Closed smit9234 closed 5 years ago

smit9234 commented 5 years ago

I am running into an issue when upgrading to Cypress 3.3.1. My current configuration is using cypress-ntlm-auth version 1.0.7 and Cypress 3.2.0.

After upgrading to Cypress 3.3.1, The plugin fails to authenticate.

I also tried using 1.0.7 version with 3.3.0 and that fails as well.

Are there specific settings needed for the proxy settings in the new version of Cypress? I am not setting any of the proxy environment variables.

Attached are the logs for v1.0.7 with 3.2.0, 3.3.0, and 3.3.1

1.0.7 - 3.2.0.txt 1.0.7 - 3.3.0.txt 1.0.7 - 3.3.1.txt

bjowes commented 5 years ago

There are no known issues with Cypress 3.3.0 or 3.3.1. I am using 3.3.1 daily without issues. I cannot see any logs of failed authentication in the logfiles you attached. Could you clarify how the Cypress test fails?

One notable difference from 3.2.0 is that Cypress handling of proxies has been optimised. It is simply better at reusing existing connections to a proxy, and this plugin acts as a proxy. That is the reason why there are much fewer NTLM handshakes in the logs for 3.3.0 and 3.3.1 compared to 3.2.0, but it should still work fine.

smit9234 commented 5 years ago

I think I found the issue, but not sure how to resolve it.

This works:

    cy.ntlm('https://labassisttest.test.site','myUserName','myPwd', 'myDomain')
    cy.visit('/')

Part of application also requires basic auth to be passed as part of the cy.visit as we have api calls that require basic auth.

    cy.ntlm('https://labassisttest.test.site','myUserName','myPwd', 'myDomain')
    cy.visit('/activities', {
    auth: {
      username: 'test',
      password: 'test'
    }
  });

So I am not sure if this is an error in Cypress or in Cypress-ntlm.

bjowes commented 5 years ago

Hmm, you have site level NTLM authentication, and then Basic authentication on a subpage on top of that? Could you clarify why you would need such a setup? Seems the first level of NTLM authentication would be sufficient.

Either way, using it like you describe will likely cause issues with the plugin, since it will attempt to perform NTLM authentication and that may interfere with Basic authentication since they use the same header in the request. Why this would have worked with Cypress 3.2.0 I can't figure out...

One reason for this behaviour is that the ntlm-proxy automatically adds a NTLM handshake header to requests going to a configured NTLM site. This is a optimisation - the alternative would be to send the request without the header, get a 401 reply, and then do the handshake. If it would have been implemented that way, the ntlm-proxy would also have seen in the 401 reply that Basic authentication was expected, not NTLM authentication.

Likely the easiest workaround for you would be to setup an alternate hostname for your site, and use that hostname when accessing the Basic authentication pages. That way the ntlm-proxy won't touch requests to the alternate hostname and Basic authentication will work fine. Something at the back of my head says that cy.Visit() won't be happy if you need to visit different sites in the same test, but I can't find any docs to support that.

bjowes commented 5 years ago

After some further thought, I found a possible explanation why it worked in 3.2.0. Could you try simply removing the auth options to the cy.visit('/activities') call?

I think what used to happen with 3.2.0 is that ntlm-proxy replaced the Basic authentication header from Cypress with a NTLM authentication header. If the site accepts either, that would work. Since 3.2.0 didn't reuse proxy connections, it would make a new connection for each request, so the authentication header would always be replaced.

Now, with 3.3.0 and up, the proxy reuses connections, and the ntlm-proxy keeps track of active connections to avoid multiple authentications on the same connection. Hence it will only replace the authentication header on the first request on a connection, and won't touch it on following requests on the same connection. That would mean that the Basic authentication header would slip through, which probably just confused the web server, resulting in a 401.

smit9234 commented 5 years ago

This makes sense.

In our app we have a few API calls that use Basic Auth for accessing the API.

I can make a cy.request() to the API endpoint using basic auth and it returns the correct response, however, because we are not passing Basic Auth credentials directly in the header on cy.visit(), then those API calls fail with a 401 when testing the app directly with Cypress.

So it looks like allowing Basic Auth wasn't supposed to happen.

bjowes commented 5 years ago

I don't follow. cy.visit() supports Basic Auth according to the docs. As long as the site isn't configured for NTLM with cy.ntlm() all the calls with cy.visit() will include the Basic Auth headers. So it should work just like cy.request().

One potential approach if you have test cases where you need to access both NTLM and Basic Auth parts of your site (with the same hostname) would be to use cy.ntlmReset before you access the Basic Auth parts, and then cy.ntlm before you access the NTLM parts. These can be called multiple times during a test. After cy.ntlmReset, the plugin won't interfere with the auth headers so Basic Auth should work.

smit9234 commented 5 years ago

Sorry this is hard to explain, as I can't share the code. But basically we have a heavily integrated application that reaches out to lots of different endpoints, and some of those endpoints don't use ntlm for authorization.

I will see if the cy.ntlmReset works for what I am trying to accomplish.

bjowes commented 5 years ago

Hi @smit9234 , any news on this?

smit9234 commented 5 years ago

@bjowes I believe this OBE, and not an issue with the plugin or cypress. All on our end, given we have way to many authentication layers.

geshan commented 5 years ago

I am having a similar issue. It works with the versions below:

"cypress": "^3.2.0",
"cypress-ntlm-auth": "^0.8.1",

but if I upgrade this library, I have to update cypress and then it comes back with a 401 with invalid credentials even though nothing has changed. It does not work with the following:

"cypress": "^3.4.0",
"cypress-ntlm-auth": "^1.2.1",

I have changed the cypress/plugins/index.js and cypress/support/index.js files as indicated in the readme. I am testing Navision BC 14 and I get the following with 401 for the newer versions, for the older versions it works:

 401 - Unauthorized: Access is denied due to invalid credentials.
You do not have permission to view this directory or page using the credentials that you supplied.
geshan commented 5 years ago

Logs from the ntlm proxy in debug mode:

DEBUG=cypress:plugin:ntlm-auth $(npm bin)/ntlm-proxy
  cypress:plugin:ntlm-auth NTLM auth config API listening on port: 55643 +0ms
  cypress:plugin:ntlm-auth NTLM auth proxy listening on port: 55644 +25ms
  cypress:plugin:ntlm-auth wrote /app_support_path/cypress-ntlm-auth/cypress-ntlm-auth.port +3ms
  cypress:plugin:ntlm-auth Startup done! +0ms
  cypress:plugin:ntlm-auth { configApiUrl: 'http://127.0.0.1:55643',
  cypress:plugin:ntlm-auth   ntlmProxyUrl: 'http://127.0.0.1:55644' } +0ms
  cypress:plugin:ntlm-auth Received alive +8s
  cypress:plugin:ntlm-auth Request to config API +8s
  cypress:plugin:ntlm-auth Created untracked agent for target http://127.0.0.1:55643/ +0ms
  cypress:plugin:ntlm-auth Received valid config update +20ms
  cypress:plugin:ntlm-auth Added new host http://myhost:80/ +0ms
  cypress:plugin:ntlm-auth Request to http://myhost:80/ in registered NTLM Hosts +38ms
  cypress:plugin:ntlm-auth Created NTLM ready agent for client 127.0.0.1:55660 to target http://myhost:80/ +0ms
  cypress:plugin:ntlm-auth Sending  NTLM message type 1 +2ms
  cypress:plugin:ntlm-auth Received NTLM message type 2, using NTLMv2 +28ms
  cypress:plugin:ntlm-auth Sending NTLM message type 3 with initial client request +2ms
  cypress:plugin:ntlm-auth NTLM authentication failed, invalid credentials. +63ms
  cypress:plugin:ntlm-auth Request to config API +1s
  cypress:plugin:ntlm-auth Created untracked agent for target http://127.0.0.1:55643/ +0ms
  cypress:plugin:ntlm-auth Received valid config update +2ms
  cypress:plugin:ntlm-auth Updating host http://myhost:80/ +0ms
  cypress:plugin:ntlm-auth Removed agent for 127.0.0.1:55660 due to socket.close +4s
bjowes commented 5 years ago

Hi @geshan, I think you have a different issue than @smit9234. Could you try using the latest beta and see if that helps? Do npm install cypress-ntlm-auth@beta

bjowes commented 5 years ago

@smit9234: Just opened #64 which should solve your use case. There are other more pressing issues I need to deal with at the moment. If you (or other users) are interested in working on that issue that would be welcome to speed up the process.

bjowes commented 5 years ago

@geshan: I have just released a new beta version, which includes a configuration option of NTLM version for each hosts. You can now do:

cy.ntlm('https://ntlm-legacy.acme.com', 'admin', 'secret', 'acme', undefined, 1);

To force usage of NTLMv1 for that particular site. This means the authentication will behave like before v1.1.0. If you want to help out finding the root cause for why the NTLMv2 fails in your case, I will be happy to continue that troubleshooting. But in the meantime you can use the new beta as a workaround.

geshan commented 5 years ago

Hello @bjowes I will try this new version and let you know of the outcome. Thanks for the continued help on this, really appreciate your concerns.

geshan commented 5 years ago

@bjowes it worked with the beta version 1.3.0-beta.3 and cypress 3.4.0, thanks for the beta release.

bjowes commented 5 years ago

Glad to hear that @geshan! Just curious - did it work out of the box or did you have to force NTLM version 1?

geshan commented 5 years ago

Worked out of the box, didn't need to force version to 1.

bjowes commented 5 years ago

Great, then I’ll close this.

bjowes commented 5 years ago

Hi @smit9234, the release 1.3.0 supports full handshake. This means the plugin will no longer enforce NTLM authentication if the server doesn't require it. Hence basic authentication for a subsite should now work out of the box. Please try it out!