Perché l’Autenticazione REST API WordPress è Critica
La REST API di WordPress espone ogni endpoint del sito: post, utenti, media, impostazioni, plugin. Senza autenticazione, chiunque può leggere dati pubblici. Ma senza un metodo di autenticazione corretto, chiunque può anche scrivere, modificare e cancellare. Nella nostra esperienza gestendo 50+ siti per agenzie, il 90% delle violazioni non passa da wp-login.php. Passa dall’API.
WordPress 5.6 ha introdotto le Application Passwords come feature nativa. Prima di quella, l’autenticazione REST API richiedeva plugin di terze parti o soluzioni custom. Oggi ci sono quattro metodi principali, ognuno con un caso d’uso specifico.
Questa guida copre tutti e quattro i metodi con codice reale che usiamo in produzione su AgencyPilot. Niente teoria accademica: solo quello che funziona nei siti dei clienti.
I 4 Metodi di Autenticazione REST API WordPress a Confronto
| Metodo | Idealmente per | Sicurezza | Complessità setup | Scadenza token |
|---|---|---|---|---|
| Cookie + Nonce | JavaScript same-domain | Alta (con nonce) | Bassa | Sessione WP |
| Application Passwords | Server-to-server, CLI, script | Media-alta | Bassa | Mai (revoca manuale) |
| JWT | SPA, mobile, headless | Alta | Media | Configurabile (15min-24h) |
| OAuth 2.0 | Integrazioni terze parti, enterprise | Massima | Alta | Access + refresh token |
Metodo 1: Cookie Authentication con Nonce
È il metodo predefinito di WordPress. Quando sei loggato in wp-admin e lanci richieste JavaScript dalla stessa origine, WordPress usa il cookie di sessione esistente. La protezione CSRF arriva tramite nonce con action wp_rest.
Implementazione cookie + nonce
Prima devi localizzare il nonce nel frontend, così JavaScript può usarlo:
// functions.php del tema o plugin
function agencypilot_enqueue_api_scripts() {
wp_enqueue_script(
'agencypilot-api',
get_template_directory_uri() . '/js/api-client.js',
array(),
'1.0.0',
true
);
wp_localize_script( 'agencypilot-api', 'wpApiSettings', array(
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' ),
) );
}
add_action( 'wp_enqueue_scripts', 'agencypilot_enqueue_api_scripts' );
Poi nel tuo JavaScript:
// api-client.js
async function updatePostTitle( postId, newTitle ) {
const response = await fetch( `${wpApiSettings.root}wp/v2/posts/${postId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce,
},
body: JSON.stringify({
title: newTitle,
}),
});
if ( ! response.ok ) {
throw new Error( `Errore API: ${response.status}` );
}
return response.json();
}
Le richieste GET su dati pubblici non hanno bisogno di nonce. Ma ogni scrittura o modifica richiede il nonce valido. Senza di quello, WordPress imposta l’utente corrente a 0 e la richiesta diventa non autenticata, anche se sei loggato.
Quando usare il cookie auth
- Pagine admin custom che parlano con la REST API
- JavaScript frontend sullo stesso dominio WordPress
- Estensioni del blocco Gutenberg
- Widget custom nella dashboard
Limiti del cookie auth
Funziona solo same-origin. Non puoi usarlo da un dominio diverso, da un’app mobile, o per comunicazione server-to-server. Se stai costruendo un frontend headless con Next.js (come abbiamo visto nella guida su WordPress Headless con Next.js 15), il cookie auth non basta.
Metodo 2: Application Passwords (nativo da WP 5.6)
Le Application Passwords sono il metodo più semplice per autenticare richieste esterne. Ogni password è una stringa di 24 caratteri generata dal sistema, legata a un utente WordPress specifico. Usa HTTP Basic Authentication: username e password vengono inviati nell’header Authorization codificati in Base64.
Generare un’Application Password
Dall’admin: Users → Profile → scorri fino a “Application Passwords” → inserisci un nome descrittivo (es. “AgencyPilot CI/CD”) → clicca “Add New Application Password”. Copia la password immediatamente perché non verrà più mostrata.
Ou via API, se hai già una password esistente:
curl -X POST https://tuosito.com/wp-json/wp/v2/users/me/application-passwords \
-u "username:password-esistente" \
-H "Content-Type: application/json" \
-d '{"name": "AgencyPilot CI/CD"}'
Usare Application Passwords nel codice
# Listare tutti i post
curl https://tuosito.com/wp-json/wp/v2/posts \
-u "username:xxxx xxxx xxxx xxxx xxxx xxxx"
# Creare un post
curl -X POST https://tuosito.com/wp-json/wp/v2/posts \
-u "username:xxxx xxxx xxxx xxxx xxxx xxxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Post via API",
"content": "Contenuto creato con Application Password",
"status": "draft"
}'
In PHP, per le nostre automazioni interne:
$credentials = base64_encode( 'username:xxxx xxxx xxxx xxxx xxxx xxxx' );
$response = wp_remote_post( 'https://tuosito.com/wp-json/wp/v2/posts', [
'headers' => [
'Authorization' => 'Basic ' . $credentials,
'Content-Type' => 'application/json',
],
'body' => json_encode([
'title' => 'Post automatico',
'content' => 'Generato da AgencyPilot',
'status' => 'draft',
]),
]);
Sicurezza delle Application Passwords
Le Application Passwords funzionano solo su HTTPS. WordPress le rifiuta su connessioni HTTP. Ogni password ha scope completo: eredita tutti i permessi dell’utente. Se l’utente è amministratore, la password può fare tutto. Per questo motivo, crea sempre un utente dedicato con permessi minimi per ogni integrazione. Mai usare l’account admin.
Puoi revocare una password in qualsiasi momento dal profilo utente. Non c’è scadenza automatica. Questo è un punto debole per ambienti enterprise: una password compromessa resta valida finché qualcuno non la revoca manualmente.
Quando usare le Application Passwords
- Script CLI e automazioni server-to-server
- Tool di CI/CD che pubblicano contenuti
- Integrazioni semplici tra servizi
- Tool di gestione multi-sito come AgencyPilot
Metodo 3: JWT (JSON Web Tokens)
I JWT sono il metodo preferito per SPA, app mobile e architetture headless. Un JWT è un token self-contained: contiene l’identità dell’utente, la data di scadenza e una firma crittografica. Il server può verificare il token senza fare lookup nel database ad ogni richiesta.
WordPress non ha JWT nativo. Serve un plugin. I due più usati sono JWT Authentication for WP REST API e Simple JWT Login.
Configurazione JWT
Dopo aver installato il plugin, devi definire una chiave segreta nel wp-config.php:
// wp-config.php
define('JWT_AUTH_SECRET_KEY', 'tua-chiave-segreta-molto-lunga-e-casuale');
define('JWT_AUTH_CORS_ENABLE', true);
Flusso di autenticazione JWT
Il client si autentica una volta con username e password. Il server risponde con un token JWT. Da quel momento, il client usa solo il token per ogni richiesta successiva.
// 1. Autenticazione: ottieni il token
async function login( username, password ) {
const response = await fetch( 'https://tuosito.com/wp-json/jwt-auth/v1/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
const data = await response.json();
localStorage.setItem( 'jwt_token', data.token );
return data.token;
}
// 2. Usa il token per le richieste successive
async function getPosts( token ) {
const response = await fetch( 'https://tuosito.com/wp-json/wp/v2/posts?status=draft', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
return response.json();
}
// 3. Verifica se il token è ancora valido
async function verifyToken( token ) {
const response = await fetch( 'https://tuosito.com/wp-json/jwt-auth/v1/token/validate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
},
});
return response.ok;
}
Vantaggi del JWT
Il token ha una scadenza configurabile. Tipicamente 15 minuti per il access token, con un refresh token per rinnovare senza ri-autenticare. Se un token viene compromesso, ha una vita limitata. Molto meglio delle Application Passwords che non scadono mai.
Il token è stateless: il server non deve salvare nulla. La firma crittografica garantisce integrità. Questo scala meglio di OAuth per applicazioni semplici.
Quando usare JWT
- Frontend headless con Next.js, Nuxt, o Astro
- App mobile che parlano con WordPress
- SPA che vivono su domini diversi da WordPress
- Sistemi con molti client che fanno richieste frequenti
Metodo 4: OAuth 2.0
OAuth 2.0 è il gold standard per integrazioni terze parti. Se stai costruendo un’app SaaS che accede a WordPress per conto di più utenti, OAuth è la scelta corretta. WordPress non ha OAuth 2.0 nativo, ma il plugin OAuth 1.0a Server e soluzioni come WP OAuth Server lo aggiungono.
Flusso OAuth 2.0 Authorization Code
- L’utente viene reindirizzato a WordPress per autorizzare l’app
- WordPress restituisce un authorization code alla tua app
- La tua app scambia il code per un access token (server-to-server)
- L’access token viene usato per le richieste API
- Quando scade, si usa il refresh token per ottenerne uno nuovo
// Scambia authorization code per access token
async function exchangeCodeForToken( code ) {
const response = await fetch( 'https://tuosito.com/wp-json/oauth/v1/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: 'your-client-id',
client_secret: 'your-client-secret',
redirect_uri: 'https://app.example.com/callback',
}),
});
return response.json();
// { access_token, refresh_token, expires_in }
}
Quando usare OAuth 2.0
OAuth ha senso quando costruisci una piattaforma dove utenti terzi autorizzano la tua app ad accedere ai loro siti WordPress. Se hai 3 integrazioni interne e sei l’unica agenzia che usa l’API, OAuth è overkill. Usa le Application Passwords o JWT.
La complessità di setup è alta: registrazione client, gestione redirect URI, rotazione dei token, storage sicuro dei refresh token. Ma per prodotti SaaS che servono più agenzie, è l’unico metodo che scales.
Sicurezza REST API WordPress: 7 Regole Non Opzionali
Dopo aver scritto l’autenticazione, la sicurezza non finisce. Queste regole valgono per qualsiasi metodo scelto:
1. Sempre HTTPS
Le Application Passwords di WordPress funzionano solo su HTTPS. Ma JWT e OAuth possono essere configurati anche su HTTP se qualcuno sbaglia il setup. Mai trasmettere token su HTTP. Un certificato SSL è il requisito minimo.
2. Princìpio del minimo privilegio
Crea utenti dedicati per ogni integrazione API. Se un tool deve solo leggere i post, usa un utente con ruolo “Contributor” o “Author”, non “Administrator”. Le Application Passwords ereditano i permessi dell’utente: se l’utente può cancellare tutto, anche la password può farlo.
3. Rate limiting sugli endpoint
Senza rate limiting, la tua REST API è vulnerabile a brute force e a abusi. Configura Nginx per limitare le richieste per IP sugli endpoint di autenticazione:
# nginx.conf
limit_req_zone $binary_remote_addr zone=api_auth:10m rate=10r/m;
location /wp-json/jwt-auth/v1/token {
limit_req zone=api_auth burst=5 nodelay;
proxy_pass http://php-fpm;
}
location /wp-json/wp/v2/users/me/application-passwords {
limit_req zone=api_auth burst=5 nodelay;
proxy_pass http://php-fpm;
}
4. Disabilitare l’API per utenti non autenticati dove serve
Alcuni endpoint REST API espongono informazioni che non vuoi rendere pubbliche. Gli utenti, ad esempio. Disabilita gli endpoint che non ti servono con rest_authentication_errors:
// Disabilita l'endpoint users per richieste non autenticate
add_filter( 'rest_endpoints', function( $endpoints ) {
if ( ! is_user_logged_in() ) {
unset( $endpoints['/wp/v2/users'] );
unset( $endpoints['/wp/v2/users/(?P[\d]+)'] );
}
return $endpoints;
});
5. Rotazione delle credenziali
Le Application Passwords non scadono. JWT sì, ma il refresh token no. Imposta un calendario per ruotare le credenziali ogni 90 giorni. Nella nostra gestione multi-sito, automatizziamo questo processo con script che generano nuove password e aggiornano le integrazioni.
6. Log delle richieste API
Registra ogni richiesta autenticata: chi, cosa, quando. Ti serve per audit di sicurezza e per debug. Un hook su rest_after_request è sufficiente:
add_action( 'rest_after_request', function( $result, $server, $request ) {
if ( is_wp_error( $result ) ) {
return $result;
}
$user_id = get_current_user_id();
if ( $user_id === 0 ) {
return $result; // Salta richieste non autenticate
}
$log_entry = sprintf(
'[%s] User %d %s %s - %s',
current_time( 'mysql' ),
$user_id,
$request->get_method(),
$request->get_route(),
$_SERVER['REMOTE_ADDR'] ?? 'unknown'
);
error_log( $log_entry, 3, WP_CONTENT_DIR . '/api-audit.log' );
return $result;
}, 10, 3 );
7. Mai hardcoded delle credenziali nel codice
Usa file di configurazione separati o variabili d’ambiente. Le credenziali nel repo Git sono la causa numero uno di compromissioni API. Niente eccezioni.
Quale Metodo Scegliere: Guida Pratica
| Scenario | Metodo consigliato | Perché |
|---|---|---|
| JavaScript sullo stesso dominio WP | Cookie + Nonce | Nativo, zero setup, zero dipendenze |
| Script CLI / cron job sul server | Application Passwords | Semplice, nativo, sufficiente per automazioni |
| Frontend headless Next.js su dominio diverso | JWT | Stateless, scadenza configurabile, perfetto per SPA |
| App mobile che parla con WordPress | JWT | Token con scadenza, refresh senza ri-login |
| SaaS multi-tenant che accede a WP di terzi | OAuth 2.0 | Consenso utente, scope limitati, rotazione token |
| Integrazione tra due servizi backend | Application Passwords | Il più rapido da setup, sufficientemente sicuro su HTTPS |
FAQ: Autenticazione REST API WordPress
Le Application Passwords sono sicure?
Sì, con tre condizioni: HTTPS obbligatorio (WordPress lo impone), utente con permessi minimi, e rotazione periodica. Il rischio principale è che non scadono automaticamente. Se una password viene compromessa, resta valida finché non la revochiamo manualmente.
Posso usare la REST API senza autenticazione?
Sì, per i dati pubblici. I post pubblicati, i termini delle tassonomie, i media pubblici sono accessibili senza auth. Ma ogni operazione di scrittura o accesso a dati privati richiede autenticazione. Mai esporre endpoint di scrittura senza auth.
JWT o Application Passwords per un frontend headless?
JWT. Le Application Passwords sono stateless nel senso sbagliato per un frontend: non scadono e non possono essere rinnovate senza rigenerarle. JWT ha scadenza configurabile e refresh token. Per un sito headless con REST API personalizzati, JWT è la scelta corretta.
Come disabilito completamente la REST API WordPress?
Puoi filtrare rest_authentication_errors per bloccare tutte le richieste non autenticate. Ma sconsiglio di disabilitarla completamente: molti plugin e il blocco editor stesso dipendono dalla REST API. Meglio disabilitare solo gli endpoint che non usi.
WordPress ha OAuth 2.0 nativo?
No. WordPress ha OAuth 1.0a tramite plugin (REST API OAuth 1.0a Server). Per OAuth 2.0 servono plugin di terze parti come WP OAuth Server. Esiste una discussione aperta nella core team su quando integrarlo nativamente, ma al 2026 non è ancora in core.