I use no authentication still sends the bearer token — my 401 assertion gets a 200
Asked 7,920 views3 answers
44votes
Deny-direction scenario, as plain as it gets:
gherkin
@api @regression
Scenario: The admin list is refused to an anonymous caller
Given I use no authentication
When I send a GET request to "/admin/users"
Then the response status should be 401
text
Expected: 401
Received: 200
The endpoint does deny anonymous callers — I checked with curl. Our envs/staging.yaml has:
yaml
api:
auth: { type: bearer }
and if I remove that block the scenario passes. So the step is not clearing anything. What is I use no authentication supposed to do?
It is supposed to send the request anonymously. It does not.
The step clears the per-scenario auth by setting it to undefined, and the API client resolves auth with ?? — which treats undefined as "nothing was specified" and falls straight through to the environment's api.auth. So your request goes out with the bearer token on it, the endpoint quite correctly answers 200, and the assertion fails. The step is a no-op whenever the environment configures auth, which is exactly the case where you would want it.
There is an open issue for this and it is not fixed.
Two things you can do today. Neither is the step working:
Run the deny direction under an environment that has no api.auth. Copy staging.yaml
to staging-anon.yaml, delete the auth block, and select it with -e staging-anon. Better still, wrap that in a named process in the project yaml so the invocation is one word and nobody has to remember the reason — see processes.
If you cannot split the environment, assert on a rejected credential instead of no
credential, and be honest in the scenario title about what you are testing:
gherkin
Given I set the request header "authorization" to "Bearer not-a-real-token"
That exercises the reject path. It is not the same test — it proves an invalid token is refused, not that an absent one is — so do not let it quietly replace the anonymous case in your coverage.
The scenarios to worry about are not the ones failing like yours. They are the ones asserting a success status after Given I use no authentication on an endpoint that is public anyway. Those pass, and they prove nothing.
Adding the audit, because you almost certainly have more than one:
bash
grep -rn 'I use no authentication' projects/<slug>/features/
Treat every hit as unverified. Split them into the ones that assert a denial — those fail loudly, you already know about them — and the ones that assert anything else. The second group is where the risk sits, and there is no signal on them at all.
We found eleven. Three were real deny-direction tests that had been quietly failing and were excluded by tag "until someone looks at it". The other eight passed and always would have.
Ours came at it from the other side, which is worth knowing about because it delays the discovery by months.
Local has no api.auth — nothing to authenticate against — so on local the step genuinely behaves anonymously and the scenarios pass honestly. It only broke when staging started requiring an API key. So a suite can be green everywhere for a long time and then a change in one environment's config turns a whole class of assertions inside out, and it will look like staging broke.