Skip to content

Testing authentication ​

An endpoint that answers correctly to the right user is half tested. The other half is that it refuses everyone else. Mistakes here are the costly kind, so every protected endpoint deserves a few deliberate attempts to get in without permission.

If the terms are new, read How APIs know who you are first.

Test only what you are allowed to

Run these tests against your own API, a test environment you have been given, or a mock. Probing someone else's system without permission is not testing.

The cases every protected endpoint needs ​

CaseSendExpect
Valid credentialsA good token200
No credentialsNo Authorization header at all401
Malformed credentialsBearer with nothing after it, or a random string401
Expired tokenA token past its time401
Wrong schemeBasic credentials where a Bearer token is expected401
Right user, wrong permissionA normal user's token on an admin endpoint403
Someone else's dataUser A's token asking for user B's order403 or 404

The last two are authorization tests. They are the ones most often missing, and the ones that find real leaks: an API that checks you are signed in but not that the order is yours.

Sign in once, reuse the token ​

Set this up before anything else, so every later request has a fresh token.

  1. Create a Sign in request as the first request in the collection. In its Captures tab, add:

    text
    token = body.token
  2. In the collection's settings, set the auth type to Bearer Token with the token {{token}}. Requests inside can then inherit it. See Authorization.

  3. Run Sign in once. From then on, every request that inherits the auth sends the token.

Keep the credentials themselves in variables, marked secret: {{email}} and {{password}}. See Variables and environments.

Build the negative cases ​

For each protected endpoint, duplicate the working request and change only its auth.

CaseHow to make it in ApiWorkbench
No credentialsSet the request's auth type to No Auth
Malformed tokenBearer Token with the value not-a-real-token
Wrong schemeBasic Auth with any username and password
Another user's dataSign in as a second test user into {{tokenB}}, and use that on user A's resource

Give each a Status equals 401 (or 403) test, and a JSON field equals on the error code if the API has one.

The Shop API sample has three ready-made: Who am I, without a token, Place an order without a token and Sign in with a wrong password.

Test the sign-in endpoint itself ​

CaseExpect
Correct email and password200 and a token
Wrong password401
Unknown email401, with the same message as a wrong password
Missing password400 or 401
Empty body400

The third row matters. If "unknown email" and "wrong password" get different answers, anyone can find out which email addresses have accounts. A test can pin that: both requests check for the same error value.

Also read the successful response critically. It should not contain the password, a password hash, or more about the user than the client needs.

Expiry and refresh ​

Tokens end. Two things to check:

  • An expired token gets 401, not a 500 and not a 200. Getting one usually means waiting, asking the server team for a short-lived test token, or testing against a mock.
  • Refresh works. If the API has a refresh endpoint, test it like sign-in: valid refresh token gives a new access token; an invalid one gives 401.

With OAuth 2.0, ApiWorkbench obtains and refreshes tokens for you. See OAuth 2.0.

Using a mock ​

Mock Studio can stand in for the lock:

  • Turn on Require auth header for an endpoint. A request without the header gets 401 before any response is chosen.
  • For a wrong-password case, use Conditional rules on the body, as the Shop API's Login does.
  • For an expired-token case, add a rule on the header: Header Authorization equals Bearer expired returns 401. Then your client's handling of expiry can be tested on demand.

A mock checks that a header is present, not that a token is genuine. It is the right tool for testing how a client behaves when refused. Whether the real API enforces its rules can only be shown against the real API. See Auth, CORS and project settings.

What to look for beyond the status ​

  • Secrets in URLs. Tokens and keys in a query string end up in logs and browser history. Prefer headers.
  • Secrets in errors. An error should never echo the credential back.
  • Plain HTTP. A protected endpoint that answers over http:// exposes every token.
  • WWW-Authenticate on a 401. The standard says it should be there; check with Header contains.

Keep your own secrets safe ​

  • Write {{token}} in requests; keep values in an environment, marked secret.
  • Review an export before sharing it. See Export and share.
  • Use accounts created for testing. Never a real person's.

Next steps ​