Skip to content
CodeKruPro

Handle 401 Unauthorized

34/62

Handle 401 Unauthorized

When you access a protected endpoint without credentials, the API returns 401 Unauthorized with a helpful error message.

Task: Access /auth/protected without any token and handle the 401 response.

Expected output:

Status: 401
Error: Missing Bearer token. Send Authorization: Bearer <token> header. Get a token from POST /api/auth/login

About this lesson

REST Assured 401 Unauthorized: test a protected endpoint without a token

Learn REST AssuredIntermediateAuthentication

How it works

Status 401 Unauthorized means the request lacked valid authentication. It is different from 403 Forbidden, which means the server knows who you are and still refuses. Testing that protected endpoints really return 401 without credentials is one of the most important security checks an API suite can make.

testkru /auth/protected answers a request with no Authorization header with 401 and a JSON error that explains what to send and where to get a token. The status line reads HTTP/1.1 401 Unauthorized. A header with another scheme, such as Basic credentials, gets the same message, because the server only looks for a Bearer value.

REST Assured does not throw on a 401. The Response is a normal object, getStatusCode() and statusCode() both return the number, and you parse the error body like any other. To make the expectation explicit, chain then().statusCode(401) with a body() check on the error text. Asserting 200 instead fails with an AssertionError that shows the 401.

About the assignment

Call the protected endpoint with no credentials at all and report the refusal: the status code and the server's full error message.

What you will do

  1. Send a plain GET to /auth/protected from given(), adding no auth and no headers.
  2. Print the status code after Status:, using getStatusCode() or statusCode().
  3. Read the error field with getString().
  4. Print it after the label Error:.

Common mistakes

  • Wrapping the call in try/catch

    Nothing is thrown for a 401, so a catch block never runs and the test passes for the wrong reason. Check the status code itself.

  • Expecting a WWW-Authenticate header

    The Basic endpoint in lesson 30 sends one, but this Bearer endpoint does not, so getHeader() returns null for it. Do not build a check on a header the contract does not promise.

  • Confusing 401 with 403

    If a test asserts 403 for a missing token it fails here, and if it accepts either code it can hide a real permissions bug. Assert the exact code the API documents.

In a real test suite

Security-minded suites run a negative test like this one for every protected route, often as a parameterised test over a list of paths. Each case asserts 401 and a stable fragment of the message with containsString().

To try one of these calls on any API endpoint without a task, open the Online Selenium Java Compiler (REST Assured is included).

Starter code

The editor above opens with this code. Fill in the TODO lines, then run and submit it.

Main.java
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import static io.restassured.RestAssured.*;

public class Main {
    public static void main(String[] args) {
        RestAssured.baseURI = "https://testkru.com/api";

        // TODO: GET /auth/protected WITHOUT any Authorization header
        // TODO: Print the status code and error message
    }
}