Skip to content

Basic and Digest Authentication

Basic and Digest authentication are standardized HTTP authentication methods defined in RFC 7617 and RFC 7616. These methods are well-suited for API access and programmatic HTTP clients.

Overview

Both Basic and Digest authentication use the HTTP Authorization header to transmit credentials. They provide automatic authentication without requiring custom login pages or session management.

Basic Authentication:

  • Simple and widely supported
  • Credentials encoded in base64 (not encrypted)
  • Must be used over HTTPS/TLS

Digest Authentication:

  • More secure than Basic
  • Uses MD5 hashing of credentials
  • Protects against replay attacks
  • Can be used over HTTP (though HTTPS still recommended)

When to Use Basic/Digest Authentication

Good Use Cases

  • REST APIs - Simple authentication for API endpoints
  • Machine-to-Machine - Automated services and scripts
  • Command-line tools - curl, wget, and similar utilities
  • Embedded clients - IoT devices communicating with server
  • Development/Testing - Quick authentication setup

When to Use Form Authentication Instead

  • Web applications - Better user experience with HTML login forms
  • Browser-based apps - Session management and logout functionality
  • Complex authentication - Multi-factor auth, OAuth integration
  • User-facing interfaces - More control over login/logout flow

How Basic Authentication Works

  1. Client requests protected resource without credentials
  2. Server responds with 401 Unauthorized and WWW-Authenticate: Basic header
  3. Client re-requests with Authorization header containing base64-encoded credentials
  4. Server decodes and validates credentials
  5. Server grants or denies access

Authorization Header Format

Authorization: Basic base64(username:password)

Example:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Where dXNlcm5hbWU6cGFzc3dvcmQ= is base64 encoding of username:password.

Configuring Basic Authentication

Enable Basic Authentication

Configure in web.json5:

js
{
    auth: {
        // Define roles with their abilities (2-level structure)
        roles: {
            public: [],
            user: ['view', 'read'],
            admin: ['user', 'edit', 'delete'],
        },

        // Enable Basic authentication
        type: "basic",

        // Authentication realm (displayed in browser dialog)
        realm: "Device Manager",
    }
}

Route Configuration

Protect routes with role requirements:

js
web: {
    routes: [
        // Require admin role
        {match: '/api/admin/', role: 'admin'},

        // Require at least user role
        {match: '/api/user/', role: 'user'},

        // Public access
        {match: '/api/public/'},

        // Catchall - public
        {},
    ],
}

Client Usage Examples

curl:

bash
curl -u username:password https://device.local/api/user/status

wget:

bash
wget --user=username --password=password https://device.local/api/user/status

JavaScript (Fetch API):

javascript
const credentials = btoa('username:password');
fetch('https://device.local/api/user/status', {
    headers: {
        'Authorization': 'Basic ' + credentials
    }
})
.then(response => response.json())
.then(data => console.log(data));

Python (requests):

python
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    'https://device.local/api/user/status',
    auth=HTTPBasicAuth('username', 'password')
)
print(response.json())

How Digest Authentication Works

  1. Client requests protected resource without credentials
  2. Server responds with 401 Unauthorized and WWW-Authenticate: Digest header containing:
    • realm - Authentication realm
    • nonce - Server-generated random value
    • qop - Quality of protection (auth, auth-int)
    • algorithm - Hash algorithm (MD5, SHA-256)
  3. Client computes hash response using:
    • Username and password
    • Server nonce
    • HTTP method and URI
    • Client nonce (if qop specified)
  4. Client re-requests with Authorization: Digest header
  5. Server validates the hash
  6. Server grants or denies access

Digest Response Calculation

HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:nonceCount:clientNonce:qop:HA2)

Configuring Digest Authentication

Enable Digest Authentication

Configure in web.json5:

js
{
    auth: {
        // Define roles with their abilities (2-level structure)
        roles: {
            public: [],
            user: ['view', 'read'],
            admin: ['user', 'edit', 'delete'],
        },

        // Enable Digest authentication
        type: "digest",

        // Authentication realm
        realm: "Device Manager",

        // Quality of protection (optional)
        qop: "auth",

        // Hash algorithm (optional, default: MD5)
        algorithm: "MD5",
    }
}

Advanced Digest Configuration

js
{
    auth: {
        type: "digest",
        realm: "Secure API",

        // Quality of protection options
        // "auth" - authentication only
        // "auth-int" - authentication with integrity protection
        qop: "auth",

        // Nonce timeout in seconds
        nonceTimeout: 300,

        // Algorithm: MD5, SHA-256, SHA-512-256
        algorithm: "SHA-256",
    }
}

Client Usage Examples

curl:

bash
curl --digest -u username:password https://device.local/api/user/status

Python (requests):

python
import requests
from requests.auth import HTTPDigestAuth

response = requests.get(
    'https://device.local/api/user/status',
    auth=HTTPDigestAuth('username', 'password')
)
print(response.json())

JavaScript: (Use a library that supports Digest auth, as native Fetch API doesn't)

Programmatic Authentication

Using webAuthenticate API

For custom authentication logic, use the webAuthenticate API:

c
static int apiHandler(Web *web)
{
    // Authenticate using configured method (Basic or Digest)
    if (!webAuthenticate(web)) {
        // Authentication failed - response already sent
        return 0;
    }

    // Get authenticated user
    cchar *username = webGetUser(web);
    cchar *role = webGetRole(web);

    // Verify user has required role
    if (!webCanUser(web, "admin")) {
        webError(web, 403, "Insufficient privileges");
        return 0;
    }

    // Process authenticated request
    webWriteResponse(web, 200, "{\"status\": \"ok\"}");
    return 0;
}

webAddAction(NULL, "/api/admin/config", apiHandler);

Custom Authentication Logic

c
static int customAuthHandler(Web *web)
{
    cchar *authHeader = webGetHeader(web, "Authorization");

    if (!authHeader) {
        // No credentials provided - request authentication
        webSetHeader(web, "WWW-Authenticate", "Basic realm=\"Device Manager\"");
        webError(web, 401, "Authentication required");
        return 0;
    }

    // Parse Authorization header
    if (strncmp(authHeader, "Basic ", 6) == 0) {
        cchar *encoded = authHeader + 6;
        cchar *decoded = cryptDecode64(encoded);

        // Parse username:password
        char *colon = strchr(decoded, ':');
        if (colon) {
            *colon = '\0';
            cchar *username = decoded;
            cchar *password = colon + 1;

            // Validate credentials
            if (validateUser(username, password)) {
                // Set authenticated user in web context
                webSetUser(web, username);
                return 1;  // Continue processing
            }
        }
    }

    // Authentication failed
    webSetHeader(web, "WWW-Authenticate", "Basic realm=\"Device Manager\"");
    webError(web, 401, "Invalid credentials");
    return 0;
}

Security Considerations

Basic Authentication Security

Vulnerabilities:

  • Credentials are only base64-encoded, not encrypted
  • Susceptible to eavesdropping on unencrypted connections
  • Credentials sent with every request (no session)

Mitigations:

  • Always use HTTPS/TLS - Essential for Basic auth
  • Use strong passwords
  • Implement rate limiting
  • Monitor for authentication failures
  • Consider IP whitelisting for sensitive APIs

Digest Authentication Security

Advantages over Basic:

  • Password never sent over network
  • Nonce prevents replay attacks
  • Server can validate without storing plaintext password

Limitations:

  • MD5 is cryptographically weak (use SHA-256 if possible)
  • Vulnerable to man-in-the-middle attacks without HTTPS
  • No protection against malicious server stealing passwords

Mitigations:

  • Use HTTPS/TLS - Still recommended for Digest
  • Use SHA-256 algorithm instead of MD5
  • Implement nonce timeout
  • Use qop="auth-int" for message integrity
  • Monitor authentication failures

General Best Practices

  1. Always use HTTPS/TLS - Even with Digest authentication
  2. Strong passwords - Enforce password complexity
  3. Rate limiting - Prevent brute force attacks
  4. Account lockout - Lock accounts after failed attempts
  5. Audit logging - Log all authentication events
  6. IP filtering - Restrict access by IP when possible
  7. Least privilege - Assign minimal required roles

Comparison: Basic vs. Digest vs. Form

FeatureBasicDigestForm
SecurityLow (requires HTTPS)MediumHigh (with HTTPS)
Setup ComplexityVery SimpleSimpleModerate
Client SupportUniversalGoodBrowsers only
User ExperienceBrowser dialogBrowser dialogCustom login page
API FriendlyYesYesNo
Session ManagementNoNoYes
Logout SupportNoNoYes
Custom UINoNoYes
HTTPS RequiredYesRecommendedYes

Mixing Authentication Methods

You can support multiple authentication methods simultaneously by checking the request type:

c
static int flexibleAuthHandler(Web *web)
{
    cchar *authHeader = webGetHeader(web, "Authorization");

    if (authHeader) {
        // API client using Basic/Digest
        if (!webAuthenticate(web)) {
            return 0;
        }
    } else {
        // Browser client - check session
        if (!webGetUser(web)) {
            webRedirect(web, 302, "/login.html");
            return 0;
        }
    }

    // User is authenticated (via API or session)
    // Continue processing...
    return 1;
}

Testing Authentication

Testing with curl

Basic authentication:

bash
# Successful authentication
curl -u admin:password https://device.local/api/user/status

# Wrong credentials
curl -u admin:wrongpass https://device.local/api/user/status

# Verbose output to see headers
curl -v -u admin:password https://device.local/api/user/status

Digest authentication:

bash
# Digest auth
curl --digest -u admin:password https://device.local/api/user/status

# See the challenge-response
curl -v --digest -u admin:password https://device.local/api/user/status

Testing Authentication Failures

Test that authentication is properly enforced:

bash
# No credentials - should return 401
curl https://device.local/api/user/status

# Insufficient role - should return 403
curl -u user:password https://device.local/api/admin/config

# Invalid credentials - should return 401
curl -u admin:wrongpass https://device.local/api/user/status

APIs

Key APIs for Basic/Digest authentication:

Samples

Example implementations:

See Also