skip to content

Direct Schemes

Credentials the DSL attaches from values you already hold. The interview point is which calls wait for the server's 401 challenge and which write the Authorization header on the very first request.

part ofREST Assuredoverview, primer and where to startread it →
on this pageshow

explore

questions

8

In REST Assured, how do you authenticate every request by default and opt one test out?

level: juniorimportance: must knowfreq 58%

answer

  1. one public static field, not a config object
  2. static factories return the scheme object
  3. default applies only when nothing else set
  4. none() is the per-request opt-out
  5. reset() restores it to NoAuthScheme

basics

~10 s

Assign a scheme to the static field RestAssured.authentication, for example RestAssured.basic(user, pass). It applies to any request that sets no scheme of its own. A single request opts out with given().auth().none().

solid answer

~40 s

`RestAssured.authentication` is a public static field of type `AuthenticationScheme`, defaulting to a `NoAuthScheme`. Assign it a scheme built by one of the static factories — `RestAssured.basic(u, p)`, `ntlm(...)`, `digest(...)`, `preemptive().basic(u, p)` — and every subsequent call inherits it. The inheritance is conditional: the default is substituted in only while the request's own `authenticationScheme` is still the implicit `NoAuthScheme`. Any per-request `auth()` call replaces it outright; nothing is merged. To make one request anonymous, use `given().auth().none()`. It installs `ExplicitNoAuthScheme`, drops auth filters and removes any `Authorization` header, so the global default is not substituted in. Call `RestAssured.reset()` afterwards to put the static back to its default.

code

java · 29 lines
java
import io.restassured.RestAssured;

import static io.restassured.RestAssured.basic;
import static io.restassured.RestAssured.given;

public class FerryDefaultAuthExample {

    public static void main(String[] args) {
        RestAssured.baseURI = "https://ferry-api.internal";
        RestAssured.authentication = basic("timetable-bot", "s3cret");

        // Inherits the default scheme.
        given()
                .queryParam("routeCode", "DOV-CAL")
        .when()
                .get("/v1/sailings")
        .then()
                .statusCode(200);

        // Opts out for this one call.
        given().auth().none()
        .when()
                .get("/v1/sailings/9f31/manifest")
        .then()
                .statusCode(401);

        RestAssured.reset();
    }
}

go deeper

for a junior

Know that RestAssured.authentication is the field to assign, that the static factories build the scheme it holds, and that given().auth().none() makes one call anonymous.

for a middle

Explain the substitution rule — the default only applies while the request's own scheme is the implicit NoAuthScheme — and why none() installs a distinct class to defeat it.

for a senior

Talk about the static as shared mutable process state: where you set it, why reset() belongs in teardown, and when a RequestSpecification carrying setAuth is the safer container.

for a principal

Decide the suite convention: whether credentials live in a global static, in a shared specification, or per call, and how that choice keeps negative authentication coverage honest.

## The static field that every request reads `io.restassured.RestAssured` exposes a public static field, `authentication`, typed `AuthenticationScheme`. It starts life as `DEFAULT_AUTH`, which is a `NoAuthScheme` — a scheme whose `authenticate(HTTPBuilder)` method does nothing at all. Assigning to it is how you say "every call in this JVM is authenticated unless told otherwise": ```java RestAssured.baseURI = "https://ferry-api.internal"; RestAssured.authentication = RestAssured.basic("timetable-bot", "s3cret"); ``` The right-hand side matters. The static `RestAssured.basic(userName, password)` is a **factory**: it builds and returns a `BasicAuthScheme` object. It is not the same thing as `given().auth().basic(...)`, which attaches a scheme to one request and returns a `RequestSpecification`. The static factories that return a scheme you can store are `basic`, `ntlm`, `digest`, `form`, `certificate`, `oauth`, `oauth2` and `preemptive().basic(...)`. ## Which static factory returns which scheme The factories on `RestAssured` are what you assign, and they are not interchangeable with the identically named methods on `given().auth()`: - `RestAssured.basic(userName, password)` returns a `BasicAuthScheme`. - `RestAssured.digest(userName, password)` also returns a `BasicAuthScheme` — its body is literally `return basic(userName, password)`. - `RestAssured.ntlm(userName, password, workstation, domain)` returns an `NTLMAuthScheme`. - `RestAssured.preemptive().basic(userName, password)` returns a `PreemptiveBasicAuthScheme`, and is the way to make the whole suite send its credential without waiting for a challenge. Each of those is an object you hold. The `given().auth()` methods of the same name return a `RequestSpecification` instead, because they attach the scheme rather than hand it to you. ## When the default is actually applied REST Assured does not merge the default into every request unconditionally. While it is building a request it performs one substitution: - If the request's own `authenticationScheme` is still the implicit `NoAuthScheme` **and** the static default is something other than a `NoAuthScheme`, the default is copied onto the request. - Otherwise the request keeps whatever it has. So the precedence rule is simple and one-directional: **a per-request `auth()` call wins, and there is no merging.** If a ferry timetable test says `given().auth().preemptive().basic("ops-reader", "hunter2")`, the global `timetable-bot` credential is never consulted for that call. ## Opting a single request out The opt-out is `given().auth().none()`. It is not a no-op and it is not the same as leaving `auth()` off the chain. `none()` does three things: 1. It sets the request's scheme to `ExplicitNoAuthScheme`. 2. It removes every `AuthFilter` from the request's filter list. 3. It removes any `Authorization` header already on the request. Step 1 is the load-bearing one. `ExplicitNoAuthScheme` implements `AuthenticationScheme` directly and is **not** a `NoAuthScheme`, so the substitution rule above sees a request that already has a scheme and leaves it alone. That single class distinction is why `none()` reliably produces an anonymous call while simply omitting `auth()` does not. This is exactly what you need for the negative half of your ferry timetable coverage: ```java given().auth().none() .when() .get("/v1/sailings/9f31/manifest") .then() .statusCode(401); ``` ## Where else a default can come from The static field is not the only place a scheme can be parked, and confusing them causes real puzzlement: - `RestAssured.requestSpecification` — a whole `RequestSpecification` applied to every call. If it was built by a `RequestSpecBuilder` with `setAuth(...)`, it carries a scheme too. - A `RequestSpecBuilder` **snapshots the statics in its constructor**, including `authentication`. A builder constructed before you assign `RestAssured.authentication` does not see the assignment. - `given().spec(someSpec)` overwrites the request's `authenticationScheme` outright rather than merging it, so call order decides which credential survives. ## Cleaning up after yourself `RestAssured.authentication` is process-wide mutable state. A suite that sets it in one test class and forgets affects every later class in the same JVM. Two habits keep that honest: - Set it once in a single place — a base class or a suite-level hook — rather than in individual tests. - Call `RestAssured.reset()` when you are done. It restores `authentication` to `DEFAULT_AUTH` along with `baseURI`, `basePath`, `rootPath`, `config`, `sessionId`, `proxy`, the filter list and both static specifications, and it puts `port` back to `UNDEFINED_PORT` (`-1`), not to `DEFAULT_PORT`. If you would rather not touch statics at all, build the credential into a `RequestSpecification` with `RequestSpecBuilder.setAuth(...)` and hand it to `given().spec(...)`. That keeps the scope explicit and makes the anonymous case the default rather than the exception — you get an unauthenticated call by simply not attaching the spec. ## The shape to remember - The default lives in one static field, `RestAssured.authentication`. - Static factories such as `RestAssured.basic(...)` produce the scheme object it holds. - The default is only substituted into requests that have set no scheme of their own. - `given().auth().none()` is the explicit per-request opt-out, and it works because the scheme it installs is a different class from the implicit one.

  • Why is given().auth().none() different from simply leaving auth() off the chain?
    Omitting `auth()` leaves the request's scheme as the implicit `NoAuthScheme`, which is exactly the condition under which REST Assured substitutes the static default in. `none()` installs `ExplicitNoAuthScheme`, a different class, so the substitution is skipped and the call really goes out unauthenticated.
  • What does RestAssured.reset() restore besides the authentication scheme?
    It restores `baseURI` to `http://localhost`, `basePath` and `rootPath` to empty, `urlEncodingEnabled` to true, `config` to a fresh `RestAssuredConfig`, and it nulls `requestSpecification`, `responseSpecification`, `defaultParser`, `sessionId` and `proxy` while emptying the filter list. Note `port` goes back to `UNDEFINED_PORT` (-1), not `DEFAULT_PORT`.

saying these in an interview costs you the question

  • Looking for auth inside RestAssuredConfig instead of the static field
  • Assuming a per-request auth() call merges with the global default
  • Thinking omitting auth() is enough to get an anonymous request
  • Setting the static in every test method and never resetting it
  • Confusing RestAssured.basic(u, p) with given().auth().basic(u, p)
open as a page

REST Assured has no auth().bearer() method - so how do you attach a bearer token to a request?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Use given().auth().oauth2(token) - REST Assured has no bearer method at all. With the default HEADER signature that call installs a PreemptiveOAuth2HeaderScheme, which writes a plain Authorization: Bearer header on the request, with no signing and no challenge round trip.

open as a page

In REST Assured, which objects do auth().basic(...) and auth().preemptive().basic(...) install on a request?

level: middleimportance: must knowfreq 64%

basics

~20 s

auth().basic(user, pass) installs a BasicAuthScheme that hands the credentials to the underlying Apache HttpClient, so the Authorization header goes out only after a 401. auth().preemptive().basic(...) installs no scheme at all and writes the header directly.

open as a page

In REST Assured, how do auth().oauth2(token) and auth().oauth2(token, OAuthSignature.QUERY_STRING) differ?

level: middleimportance: must knowfreq 48%

basics

~20 s

The default HEADER form installs PreemptiveOAuth2HeaderScheme and writes a plain Authorization: Bearer header. The QUERY_STRING form installs OAuth2Scheme, which signs the request through scribejava and moves the credential into the URI, so it needs the optional scribejava-apis artifact.

open as a page

In REST Assured, why does RestAssured.oauth2(token, OAuthSignature.HEADER) install a different scheme than auth().oauth2(token, HEADER)?

level: middleimportance: should knowfreq 31%

basics

~20 s

The instance method branches on the signature and the static factory does not. auth().oauth2(token, HEADER) installs PreemptiveOAuth2HeaderScheme and writes a plain Bearer header, while the two-argument static RestAssured.oauth2 unconditionally builds OAuth2Scheme, routing the request through the optional scribejava signing path.

open as a page

Your REST Assured suite sets RestAssured.authentication globally and a test expecting 401 gets 200. How do you fix it?

level: seniorimportance: should knowfreq 41%

basics

~10 s

The test never called auth(), so its scheme was still the implicit NoAuthScheme and REST Assured substituted the global default in. Add given().auth().none(), which installs ExplicitNoAuthScheme and blocks that substitution.

open as a page

In REST Assured, what does auth().preemptive().oauth2(token) change on a request that auth().oauth2(token) does not?

level: seniorimportance: should knowfreq 34%

basics

~20 s

On the wire, nothing: both send Authorization: Bearer plus the token. The preemptive form calls auth().none() first, clearing the scheme, its auth filters and any Authorization header, then sets the header immediately; the plain form defers it until send time.

open as a page

In REST Assured, what scheme object does auth().digest(user, password) actually install?

level: middleimportance: nice to knowfreq 34%

basics

~10 s

A BasicAuthScheme. REST Assured ships no digest-specific scheme class; the static RestAssured.digest(user, password) simply returns basic(user, password). The credentials are stored for the HTTP client, which answers whichever challenge the server sends.

open as a page