Intermediate Chapter 8 · 12 min read

Authentication & Authorization

Implement Bearer tokens, Basic auth, API keys, and OAuth2 flows. Test protected endpoints and validate access control.

API Authentication & Authorization

Most real-world APIs require authentication. Understanding different auth mechanisms and testing them properly is crucial for any API tester.

Common Authentication Methods

  • Bearer Token — A token (often JWT) sent in the Authorization header. Most common in modern APIs.
  • Basic Auth — Username and password encoded in Base64. Simple but less secure.
  • API Key — A static key sent as a header or query parameter. Common in third-party APIs.
  • OAuth 2.0 — A delegation framework for granting limited access. Used by Google, GitHub, etc.

What to Test

Test both happy paths (valid credentials) and negative scenarios: expired tokens, invalid tokens, missing auth, wrong permissions, and token refresh flows.

auth.test.js
// Bearer Token Authentication
const token = 'your-jwt-token-here';

const bearerResponse = await fetch('https://httpbin.org/bearer', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});
console.log('Bearer status:', bearerResponse.status);

// Basic Authentication
const username = 'testuser';
const password = 'testpass';
const basicCredentials = btoa(`${username}:${password}`);

const basicResponse = await fetch(
  `https://httpbin.org/basic-auth/${username}/${password}`, {
  headers: {
    'Authorization': `Basic ${basicCredentials}`
  }
});
const basicData = await basicResponse.json();
console.assert(basicResponse.status === 200);
console.assert(basicData.authenticated === true);

// API Key in header
const apiKeyResponse = await fetch('https://httpbin.org/headers', {
  headers: {
    'X-API-Key': 'my-secret-api-key'
  }
});
const apiData = await apiKeyResponse.json();
console.log('API Key sent:', apiData.headers['X-Api-Key']);

// API Key as query parameter
const apiKeyQueryResp = await fetch(
  'https://httpbin.org/get?api_key=my-secret-api-key'
);

// Test missing auth — should return 401
const noAuthResponse = await fetch('https://httpbin.org/bearer');
console.assert(noAuthResponse.status === 401, 'Should be 401 without token');

// Reusable auth helper
function createAuthHeaders(token) {
  return {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  };
}

console.log('All auth tests passed!');
AuthenticationTest.java
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import io.restassured.specification.RequestSpecification;
import org.testng.annotations.Test;

public class AuthenticationTest {

    @Test
    public void testBearerToken() {
        String token = "your-jwt-token-here";

        given()
            .header("Authorization", "Bearer " + token)
        .when()
            .get("https://httpbin.org/bearer")
        .then()
            .statusCode(200)
            .body("authenticated", equalTo(true));
    }

    @Test
    public void testBasicAuth() {
        given()
            .auth().preemptive().basic("testuser", "testpass")
        .when()
            .get("https://httpbin.org/basic-auth/testuser/testpass")
        .then()
            .statusCode(200)
            .body("authenticated", equalTo(true))
            .body("user", equalTo("testuser"));
    }

    @Test
    public void testApiKeyInHeader() {
        given()
            .header("X-API-Key", "my-secret-api-key")
        .when()
            .get("https://httpbin.org/headers")
        .then()
            .statusCode(200)
            .body("headers.X-Api-Key", equalTo("my-secret-api-key"));
    }

    @Test
    public void testMissingAuth_ShouldReturn401() {
        given()
        .when()
            .get("https://httpbin.org/bearer")
        .then()
            .statusCode(401);
    }

    // Reusable auth spec
    private RequestSpecification authSpec(String token) {
        return given()
            .header("Authorization", "Bearer " + token)
            .contentType("application/json");
    }
}
test_authentication.py
import requests
from requests.auth import HTTPBasicAuth
import base64

def test_bearer_token():
    """Bearer token authentication"""
    token = 'your-jwt-token-here'

    response = requests.get(
        'https://httpbin.org/bearer',
        headers={'Authorization': f'Bearer {token}'}
    )
    assert response.status_code == 200
    assert response.json()['authenticated'] is True

def test_basic_auth():
    """Basic authentication — Requests makes this easy"""
    response = requests.get(
        'https://httpbin.org/basic-auth/testuser/testpass',
        auth=HTTPBasicAuth('testuser', 'testpass')
    )
    assert response.status_code == 200
    assert response.json()['authenticated'] is True
    assert response.json()['user'] == 'testuser'

def test_api_key_header():
    """API key in custom header"""
    response = requests.get(
        'https://httpbin.org/headers',
        headers={'X-API-Key': 'my-secret-api-key'}
    )
    assert response.status_code == 200
    assert response.json()['headers']['X-Api-Key'] == 'my-secret-api-key'

def test_api_key_query_param():
    """API key as query parameter"""
    response = requests.get(
        'https://httpbin.org/get',
        params={'api_key': 'my-secret-api-key'}
    )
    assert response.status_code == 200

def test_missing_auth():
    """Missing auth should return 401"""
    response = requests.get('https://httpbin.org/bearer')
    assert response.status_code == 401

# Reusable session with auth
def create_auth_session(token):
    session = requests.Session()
    session.headers.update({
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    })
    return session

API Testing Intermediate Authentication & Authorization

Written by PV

© 2026 All Rights Reserved