LESSON 3 โฑ๏ธ 14 min read

Authentication: Securing API Access

Why Authentication?

Read operations (GET) on public content don't require authentication. But to:

  • Create, update, or delete content
  • Access private/draft posts
  • Modify settings
  • Access user data

You need to authenticate your requests.

Authentication Methods

MethodBest ForSecurity Level
Application PasswordsServer-to-server, personal scriptsGood
JWT TokensSPAs, mobile appsBetter
OAuth 2.0Third-party appsBest
Cookie AuthSame-domain JavaScriptBuilt-in

Application Passwords (WordPress 5.6+)

The simplest method โ€“ built into WordPress core.

Creating an Application Password

  1. Go to Users โ†’ Profile
  2. Scroll to Application Passwords
  3. Enter a name (e.g., "My Script")
  4. Click Add New Application Password
  5. Copy the generated password (shown only once!)

Using Application Passwords

# Encode credentials as Base64
echo -n "username:application_password" | base64
# Result: dXNlcm5hbWU6YXBwbGljYXRpb25fcGFzc3dvcmQ=

# Use in requests
curl -X POST https://site.com/wp-json/wp/v2/posts 
    -H "Authorization: Basic dXNlcm5hbWU6YXBwbGljYXRpb25fcGFzc3dvcmQ=" 
    -H "Content-Type: application/json" 
    -d '{"title":"New Post","content":"Hello!","status":"publish"}'

JavaScript Example

const credentials = btoa('username:xxxx xxxx xxxx xxxx xxxx xxxx');

async function createPost(title, content) {
    const response = await fetch('/wp-json/wp/v2/posts', {
        method: 'POST',
        headers: {
            'Authorization': `Basic ${credentials}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            title,
            content,
            status: 'publish'
        })
    });
    
    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    return response.json();
}
Security: Never expose Application Passwords in client-side JavaScript! Use them only in server-side code or secure environments.

JWT Authentication

JSON Web Tokens are better for client applications. Install a JWT plugin like JWT Authentication for WP REST API.

Setup

  1. Install the JWT plugin
  2. Add to wp-config.php:
define('JWT_AUTH_SECRET_KEY', 'your-secret-key-here');
define('JWT_AUTH_CORS_ENABLE', true);
  1. Add to .htaccess:
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]

Getting a Token

async function getToken(username, password) {
    const response = await fetch('/wp-json/jwt-auth/v1/token', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ username, password })
    });
    
    const data = await response.json();
    
    if (data.token) {
        return data.token;
    }
    
    throw new Error(data.message);
}

Using the Token

const token = await getToken('admin', 'password');

// Use token in subsequent requests
const response = await fetch('/wp-json/wp/v2/posts', {
    method: 'POST',
    headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        title: 'JWT Authenticated Post',
        content: 'Created with JWT!',
        status: 'publish'
    })
});

Token Validation

async function validateToken(token) {
    const response = await fetch('/wp-json/jwt-auth/v1/token/validate', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`
        }
    });
    
    return response.ok;
}

Cookie Authentication (Same Domain)

For JavaScript running on WordPress itself, use the built-in nonce:

// Enqueue script with nonce
wp_enqueue_script('my-api-script', 'path/to/script.js', ['wp-api-fetch'], '1.0', true);
wp_localize_script('my-api-script', 'myApiSettings', [
    'nonce' => wp_create_nonce('wp_rest'),
    'root'  => esc_url_raw(rest_url())
]);
// In your JavaScript
async function createPost(title, content) {
    const response = await fetch(`${myApiSettings.root}wp/v2/posts`, {
        method: 'POST',
        headers: {
            'X-WP-Nonce': myApiSettings.nonce,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ title, content, status: 'publish' })
    });
    
    return response.json();
}
Note: Cookie authentication only works when the user is logged into WordPress and the request comes from the same domain.

OAuth 2.0 (For Third-Party Apps)

For apps that need to authenticate multiple users, use OAuth. Install WP OAuth Server or similar.

// OAuth 2.0 flow (simplified)
const clientId = 'your_client_id';
const redirectUri = 'https://yourapp.com/callback';

// 1. Redirect user to authorize
const authUrl = `https://site.com/oauth/authorize?
    client_id=${clientId}&
    redirect_uri=${encodeURIComponent(redirectUri)}&
    response_type=code`;

window.location = authUrl;

// 2. Exchange code for token (on your server)
async function exchangeCodeForToken(code) {
    const response = await fetch('https://site.com/oauth/token', {
        method: 'POST',
        body: new URLSearchParams({
            grant_type: 'authorization_code',
            code,
            client_id: clientId,
            client_secret: 'your_secret',
            redirect_uri: redirectUri
        })
    });
    
    return response.json();
}

Handling Authentication Errors

async function apiRequest(endpoint, options = {}) {
    const response = await fetch(endpoint, {
        ...options,
        headers: {
            'Authorization': `Bearer ${getStoredToken()}`,
            'Content-Type': 'application/json',
            ...options.headers
        }
    });
    
    if (response.status === 401) {
        // Token expired or invalid
        clearStoredToken();
        redirectToLogin();
        return;
    }
    
    if (response.status === 403) {
        throw new Error('You do not have permission to perform this action');
    }
    
    if (!response.ok) {
        const error = await response.json();
        throw new Error(error.message || 'API request failed');
    }
    
    return response.json();
}

Next Steps

In the next lesson, we'll perform write operations โ€“ creating, updating, and deleting posts, pages, and other content via the API.

๐ŸŽฏ Lesson Complete! You can now authenticate API requests using multiple methods for different use cases.