Resposta curta: na REST API do WordPress, autenticação e autorização são etapas diferentes. Quando a requisição usa a autenticação por cookies do próprio WordPress, o nonce de ação wp_rest ajuda o core a validar a intenção da requisição e a associá-la à sessão autenticada. Ele não concede permissão para ler, criar, alterar ou excluir recursos. A decisão de acesso deve ficar em permission_callback, normalmente com current_user_can() e uma capability adequada ao recurso.
Essa separação evita um erro comum: considerar que uma requisição com X-WP-Nonce válido já está autorizada. Um usuário pode estar autenticado e, ainda assim, não ter a capability exigida. A documentação oficial do WordPress recomenda checar o que o usuário pode fazer, em vez de apenas verificar se ele está logado.
Autenticação e autorização respondem a perguntas diferentes
| Camada | Pergunta | Mecanismo típico |
|---|---|---|
| Autenticação | Quem está fazendo a requisição? | Cookies do WordPress com nonce wp_rest, Application Passwords ou outro método de autenticação |
| Autorização | Esse usuário pode executar esta ação? | permission_callback com current_user_can() ou outra regra de acesso |
| Execução | O que acontece depois que o acesso foi aprovado? | callback da rota, com validação, sanitização e lógica de negócio |
O fluxo seguro é simples: primeiro o WordPress resolve a autenticação disponível; depois, antes do callback principal, executa o permission_callback. Só se a permissão for concedida a lógica da rota deve prosseguir.
O que o nonce do REST realmente faz
Na autenticação por cookies, usada principalmente quando JavaScript roda dentro de um site WordPress com o usuário já logado, o cliente envia um nonce criado para a ação wp_rest. O valor pode ir no cabeçalho X-WP-Nonce ou no parâmetro _wpnonce. A documentação recomenda o cabeçalho, que funciona de forma consistente para diferentes métodos HTTP.
Se a requisição usa cookies mas não apresenta um nonce REST válido, o core não deve tratar a sessão como autenticada para aquela chamada. A documentação do REST API Handbook explica que, sem o nonce, o usuário atual é definido como ID 0, fazendo a chamada se comportar como não autenticada. Quando o nonce é inválido, o mecanismo de autenticação por cookies pode encerrar a requisição com erro.
Para endpoints customizados, não é necessário repetir manualmente a verificação do nonce wp_rest dentro do callback. O core faz essa checagem na autenticação de cookies, por meio de rest_cookie_check_errors(). O ponto essencial é que isso não substitui autorização. A documentação geral de nonces do WordPress afirma explicitamente que nonces não devem ser usados como controle de acesso e recomenda proteger operações com current_user_can().
Há ainda uma nuance importante: os nonces do WordPress não são tokens de uso único no sentido criptográfico estrito. Eles têm janela de validade e podem ser reutilizados dentro dela. Portanto, não devem ser tratados como segredo equivalente a uma senha nem como prova suficiente de permissão.
Como registrar uma rota privada com permission_callback
Considere uma rota que altera uma configuração do plugin. Como a operação é administrativa, o exemplo abaixo exige a capability manage_options. Em um plugin real, escolha a capability mais específica compatível com a ação.
<?php add_action( 'rest_api_init', function () { register_rest_route( 'acme/v1', '/settings', array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => 'acme_update_settings', 'permission_callback' => 'acme_update_settings_permissions_check', 'args' => array( 'value' => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), ), ) ); } ); function acme_update_settings_permissions_check( WP_REST_Request $request ) { if ( ! current_user_can( 'manage_options' ) ) { return new WP_Error( 'acme_rest_forbidden', __( 'You are not allowed to change this setting.', 'acme' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } function acme_update_settings( WP_REST_Request $request ) { $value = $request->get_param( 'value' ); update_option( 'acme_example_value', $value ); return rest_ensure_response( array( 'success' => true, 'value' => $value, ) ); }O permission_callback pode retornar true, false ou um WP_Error. Retornar um WP_Error é útil quando você quer um código e uma mensagem específicos. Se retornar false ou null, o servidor REST cria uma resposta de acesso negado. O helper rest_authorization_required_code() retorna 401 para visitante não autenticado e 403 para usuário autenticado que não pode executar a ação.
Desde o WordPress 5.5, registrar uma rota sem permission_callback gera um aviso de uso incorreto. Em rotas realmente públicas, __return_true pode ser apropriado. Em rotas privadas, usar __return_true apenas para eliminar o aviso remove justamente a barreira de autorização.
Três cenários que mostram por que o nonce não basta
| Cenário | Autenticação | Autorização | Resultado esperado |
|---|---|---|---|
| Visitante anônimo | Não há sessão autenticada | current_user_can() falha | Acesso negado, normalmente 401 |
| Usuário logado com nonce válido, mas sem capability | A sessão pode ser reconhecida | current_user_can() falha | Acesso negado, normalmente 403 |
| Usuário logado com nonce válido e capability necessária | A sessão é reconhecida | current_user_can() passa | O callback da rota é executado |
O segundo cenário é o teste mental mais importante. Um nonce válido pode acompanhar a requisição de um assinante, autor ou outro usuário sem a permissão necessária. Se a rota só verificar nonce ou apenas is_user_logged_in(), ela pode expor uma operação que deveria ficar restrita.
Quando usar nonce e quando usar outro método de autenticação
O nonce wp_rest faz sentido no fluxo de autenticação por cookies, especialmente em telas administrativas, blocos, plugins ou front-ends renderizados pelo próprio WordPress, em que o navegador já possui os cookies da sessão. Nesse caso, o JavaScript envia o nonce junto da chamada REST.
Para integrações externas, serviços em outro servidor, scripts de automação ou clientes que não compartilham a sessão de cookies do navegador, a própria documentação do WordPress apresenta Application Passwords como método nativo para autenticação REST sobre HTTPS. Mesmo usando Application Passwords, a autorização da rota continua sendo responsabilidade do permission_callback.
Em outras palavras, o método de autenticação pode mudar, mas a regra de autorização permanece. O endpoint deve decidir se a identidade autenticada pode executar a operação solicitada.
Prefira capabilities a nomes de papéis
current_user_can() deve receber uma capability que represente a ação. Verificar diretamente se o usuário é administrator, editor ou outro papel cria acoplamento desnecessário e pode falhar em sites que personalizam papéis e capacidades.
Quando a autorização depende de um objeto, prefira uma meta capability com o ID correspondente. Para editar um post específico, por exemplo:
function acme_update_post_permissions_check( WP_REST_Request $request ) { $post_id = (int) $request['id']; return current_user_can( 'edit_post', $post_id ); }O WordPress mapeia meta capabilities como edit_post para as capacidades primitivas necessárias conforme o usuário, o objeto e o contexto. Isso é mais preciso do que uma checagem genérica como edit_posts quando a decisão depende de um item específico.
Erros comuns ao proteger uma rota REST
- Usar nonce como autorização: ele ajuda a proteger o fluxo de requisição, mas não diz se o usuário pode executar a ação.
- Checar apenas se o usuário está logado: autenticação sem capability pode conceder acesso excessivo a contas de baixo privilégio.
- Colocar toda a autorização dentro do callback principal: a checagem deve acontecer em permission_callback, antes da lógica de negócio.
- Usar __return_true em endpoint privado: isso torna a rota publicamente autorizada, ainda que o callback depois tente compensar.
- Verificar papel em vez de capability: capabilities são a abstração prevista pelo WordPress para autorização.
- Revalidar manualmente o nonce REST sem necessidade: no fluxo padrão de cookies, o core já valida wp_rest. Duplique apenas se houver outro requisito de segurança independente e bem definido.
- Confiar em parâmetros enviados pelo cliente para decidir privilégio: IDs e argumentos podem orientar a checagem, mas a decisão deve ser feita no servidor com dados e capabilities confiáveis.
Teste de regressão: anônimo, usuário sem capability e usuário autorizado
Além de testar o caso de sucesso, mantenha testes que provem que a rota continua negando acesso quando a autenticação ou a capability mudam. Um teste de unidade ou integração pode despachar uma WP_REST_Request diretamente ao servidor REST para validar a regra de autorização.
<?php public function test_settings_route_permissions() { $server = rest_get_server(); wp_set_current_user( 0 ); $request = new WP_REST_Request( 'POST', '/acme/v1/settings' ); $request->set_param( 'value', 'one' ); $response = $server->dispatch( $request ); $this->assertSame( 401, $response->get_status() ); $subscriber_id = self::factory()->user->create( array( 'role' => 'subscriber' ) ); wp_set_current_user( $subscriber_id ); $request = new WP_REST_Request( 'POST', '/acme/v1/settings' ); $request->set_param( 'value', 'two' ); $response = $server->dispatch( $request ); $this->assertSame( 403, $response->get_status() ); $admin_id = self::factory()->user->create( array( 'role' => 'administrator' ) ); wp_set_current_user( $admin_id ); $request = new WP_REST_Request( 'POST', '/acme/v1/settings' ); $request->set_param( 'value', 'three' ); $response = $server->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); }Esse teste cobre a autorização do endpoint. Se o plugin depende de JavaScript autenticado por cookies, adicione também um teste de integração HTTP para o fluxo de nonce: sessão logada sem X-WP-Nonce, nonce inválido, nonce válido com usuário sem capability e nonce válido com usuário autorizado. Assim você separa regressões de autenticação de regressões de autorização.
Checklist para uma rota REST privada
- Registre a rota em rest_api_init.
- Defina explicitamente permission_callback.
- Escolha uma capability ligada à ação real, usando meta capability e ID quando necessário.
- Use nonce wp_rest apenas quando a chamada depender da autenticação por cookies.
- Para clientes externos, use um método de autenticação apropriado, como Application Passwords sobre HTTPS.
- Valide e sanitize argumentos da requisição separadamente da autorização.
- Mantenha o callback principal focado na lógica da operação depois que a permissão foi aprovada.
- Teste pelo menos os cenários anônimo, autenticado sem capability e autenticado com capability.





