I am trying to access audio snippets within an application hosted on Azure blob storage during a cypress test and I keep getting
"403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."
The app works fine when I use it manually through browser, but fails during Cypress run.
this is my cypress config
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
baseUrl: 'https://tts-sa-dev.azurewebsites.net',
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
I use a basic auth before every test suite
beforeEach(() => cy.authenticate('basic'));
that looks like this
Cypress.Commands.add('authenticate', (authType: 'basic') => {
if (authType === 'basic') {
const username = 'XXXX';
const password = 'XXXX';
const authHeader = 'Basic ' + btoa(username + ':' + password);
// Intercept all requests and add the Authorization header
cy.intercept('**', (req) => {
req.headers['Authorization'] = authHeader;
});
}
});
Im not sure if the auth header could be somehow interacting with the cors signature from azure and there seems to be nobody else on stackoverflow dealing with this, which i find strange.
I’ve simplified the test to bare bones, but it fails to retrieve any data after calling the endpoint.
I realize cypress is probably modifying the request header but I fail to log any difference when intercepting it.
Anybody has a similar problem?
I have compared request headers and there were some discrepancies:
There was an "origin" header missing, "accept" was an array of options and "fetch-mode" was non-cors, but adjusting them made no difference.
cy.intercept('*', (req) => {
console.log('Request Headers at Intercept:', req.headers);
req.headers['Accept'] = 'application/json';
req.headers['Origin'] = 'https://xxxx.azurewebsites.net';
req.headers['Sec-Fetch-Mode'] = 'cors';
req.headers['Accept-Language'] = 'cs,en;q=0.9';
});
2
Answers
Ok so I've found a solution - the problem seems to be in the basic auth
Azure has some kind of a problem with basic auth and doesn't do well with authorization header.
Instead I have used
Works fine now
I think you need header names to start lower case.
If you look at Passing a request to the next request handler, it uses lower-case
authorization
but you have upper-caseAuthorization
.If I try a sample test with
req.headers['Origin']
it passes (but it shouldn’t)In the final
console.log()
there are upper-case and lower-case headers for "Origin/origin" keys, which indicates the header key is case sensitive.If I switch to lower-case
req.headers['origin']
it now fails with a CORS error, which I think is correct behavior.From that I would conclude the correct format for setting header keys is to use lower-case strings.
Not sure this is the complete answer, but should get you one step further.
Basic auth on cy.visit()
The cy.visit() – Add basic auth headers documentation shows how to use basic auth in the visit command.
This should make a single test test authenticated, push to
beforeEach()
to do it for each test.Wrap in a cy.session to cache the login credentials.