Início » Blog » Chaves de API no WordPress: como armazenar credenciais com segurança

Chaves de API no WordPress: como armazenar credenciais com segurança

Por Leonardo Marioto

Atualizado em

Chaves de API no WordPress: como armazenar credenciais com segurança

Recentemente, recebi um e-mail do Google Cloud sobre práticas recomendadas para proteger chaves de API e credenciais de contas de serviço.

A mensagem não informava que uma chave havia sido vazada ou que um projeto tinha sido invadido. Era um alerta preventivo, mas daqueles que vale a pena levar a sério, principalmente quando administramos sites de clientes e integrações que continuam funcionando por meses ou anos.

Dentre outras coisas, o e-mail alertava o seguinte:

Proteja o ciclo de vida das credenciais: aplique o nível de segurança padrão seguindo estas práticas recomendadas:

  • Use um armazenamento sem código: nunca faça commit de chaves no código-fonte ou no controle de versões. Para injetar credenciais no ambiente de execução, use o Secret Manager.
  • Desabilite chaves inativas: audite suas chaves ativas e desative as que não mostraram atividade nos últimos 30 dias.
  • Aplique restrições de API: nunca deixe uma chave de API sem restrições. Limite as chaves a APIs específicas (por exemplo, apenas JavaScript do Maps) e aplique restrições ambientais (endereços IP, referenciadores HTTP ou IDs de pacote).
  • Aplique o princípio de privilégio mínimo: nunca conceda permissões totais a uma conta de serviço. Use o recomendador do IAM para remover permissões não usadas de contas de serviço e defina apenas o acesso mínimo absolutamente necessário para a função delas.
  • Aplique a rotação obrigatória: implemente a política iam.serviceAccountKeyExpiryHours para que todas as chaves de contas de serviço gerenciadas pelos usuários tenham um ciclo de vida máximo. Se essas chaves não forem necessárias, implemente iam.managed.disableServiceAccountKeyCreation para desativar a criação de novas chaves.

Tenho clientes que utilizam integrações externas em projetos WordPress: mapas, envio de e-mails, login social, pagamentos, armazenamento, automações e outras APIs. Algumas passam pelo Google, mas muitas pertencem a outros serviços.

Um erro que eu também cometia

No início, já adicionei credenciais diretamente ao functions.php do tema filho 😬

Tecnicamente, isso pode fazer a integração funcionar. Mas em termos de arquitetura e segurança, não é o lugar correto para armazenar um segredo. Com o tempo, passei a separar melhor o código da aplicação, a configuração do ambiente e as credenciais que permitem acesso a serviços externos.

Neste artigo, vou usar o aviso como ponto de partida para explicar, de forma prática, onde guardar credenciais no WordPress, quando o wp-config.php é a melhor alternativa disponível e quais cuidados fazem sentido em projetos reais de clientes.

Por que isso importa em projetos WordPress?

Uma credencial de longa duração funciona como uma chave que continua abrindo a porta até que alguém a restrinja, desative ou substitua.

Isso vale para vários serviços usados no dia a dia de um site: envio de e-mails, mapas, login social, pagamentos, automações, armazenamento e integrações feitas sob medida. Se uma credencial aparecer em um backup, log de erro, arquivo público ou repositório, outra pessoa poderá tentar utilizá-la.

Para quem trabalha como freelancer, também é uma questão de responsabilidade profissional. O cliente geralmente não sabe que existe uma chave por trás de um formulário, mapa ou automação. Somos nós que precisamos entender onde ela está, quem pode acessá-la e o que deve acontecer quando o projeto ou a integração termina.

Importante: receber esse tipo de e-mail não significa, por si só, que houve um incidente. Ele apenas serve como um bom lembrete para revisar integrações antigas e credenciais que podem ter sido esquecidas.

Chave de API, conta de serviço e OAuth: o que realmente é um segredo?

Antes de decidir onde armazenar uma credencial, precisamos entender o que ela representa. Nem todo identificador exposto no navegador é uma falha, e nem toda informação chamada de “chave” possui o mesmo nível de risco.

Chaves de API

Uma chave de API identifica o projeto que faz a chamada e permite o uso das APIs que aceitam esse tipo de credencial. Dependendo do serviço, ela também ajuda a controlar limites de uso e cobranças.

Quando a integração funciona no servidor, a chave não deve aparecer no código enviado ao navegador. O ideal é armazená-la de forma protegida e utilizá-la apenas no momento em que o WordPress fizer a comunicação com a API.

Em um dos meus projetos, por exemplo, o cliente precisava exibir mapas interativos. Para isso, utilizei a Places API, cuja chave precisa chegar ao navegador para que o mapa seja carregado. Por esse motivo, ela pode ser encontrada por quem inspecionar a página.

Nesse caso, a segurança está principalmente nas restrições configuradas no Google Cloud. É possível permitir que a chave acesse somente a API necessária e funcione apenas nos domínios autorizados. Assim, mesmo que ela seja visualizada, fica muito mais difícil utilizá-la indevidamente em outro site.

Um formulário de solicitação de orçamento é exibido com campos para local de coleta, data, horário e número de passageiros. O menu suspenso usa a API do Google Places para sugerir locais que começam com Flórida. O botão Concluído está na parte inferior.
Exemplo de sugestão de endereços enquanto a pessoa digita

Contas de serviço

As contas de serviço aparecem com menos frequência em um site WordPress comum, mas podem fazer parte de integrações personalizadas. Elas funcionam como um usuário criado para a aplicação: em vez de uma pessoa fazer login, o sistema acessa apenas os recursos permitidos.

Ao criar uma chave para essa conta, o Google disponibiliza um arquivo JSON com uma credencial privada. Esse arquivo exige bastante cuidado: quem conseguir copiá-lo poderá se autenticar como a aplicação e utilizar as permissões concedidas à conta de serviço.

Por isso, ele não deve ser incluído no tema, colocado em uma pasta pública do site, enviado para um repositório ou compartilhado sem necessidade.

O Google recomenda evitar chaves permanentes de contas de serviço sempre que houver outra opção. Em uma hospedagem WordPress convencional, quando o arquivo JSON for realmente necessário, ele deve ficar fora das pastas públicas do site, com acesso restrito e somente com as permissões indispensáveis.

OAuth, tokens e segredos de webhook

As integrações que utilizam OAuth normalmente trabalham com diferentes tipos de credenciais. O client_id serve para identificar a aplicação e, em muitos casos, pode aparecer durante o processo de conexão.

Já o client_secret e os tokens gerados após a autorização precisam permanecer protegidos. Esses valores podem permitir que a aplicação consulte informações ou execute ações na conta conectada.

Quando um serviço fornece um segredo para validar webhooks, esse valor também deve ser protegido. É ele que ajuda o site a confirmar que a notificação veio do serviço correto.

No WordPress, essas credenciais costumam ser configuradas em plugins específicos, como o WP Mail SMTP e as soluções de login social. Os webhooks, por sua vez, são comuns em integrações do WooCommerce com gateways de pagamento, ERPs e outros serviços externos.

O próprio WP Mail SMTP permite definir credenciais por meio de constantes no wp-config.php:

Exemplo de configuração do plugin WP Mail SMTP com recomendação de armazenamento no arquivo de configuração

functions.php ou wp-config.php: qual é o lugar correto?

Como já contei, no início da minha carreira como freelancer, eu armazenava algumas credenciais e configurações sensíveis diretamente no functions.php (e, em alguns casos, até nos próprios scripts).

Nota: o functions.php é um arquivo do tema utilizado para adicionar ou modificar funcionalidades do WordPress. Já o wp-config.php reúne configurações gerais da instalação, como os dados de acesso ao banco e outras constantes utilizadas pelo sistema, sem ficar vinculado ao tema ativo.

Se a escolha estiver apenas entre esses dois arquivos, o wp-config.php é mais adequado para disponibilizar uma configuração sensível ao WordPress. Como ele fica fora do tema, a credencial não acompanha um ZIP ou o repositório do tema filho e também não deixa de funcionar caso o tema seja trocado.

O functions.php, por outro lado, é carregado somente com o tema ativo. Por isso, não é um bom lugar para guardar credenciais ou manter integrações que precisam continuar funcionando independentemente do tema utilizado.

Também é importante separar a credencial do restante da integração. O wp-config.php pode disponibilizar o valor necessário, mas não deve receber funções, hooks ou requisições. Se a integração precisa sobreviver a uma troca de tema, sua lógica deve ficar em um plugin próprio. O tema filho deve concentrar apenas o código realmente ligado à aparência ou ao comportamento daquele tema.

No artigo Segurança WordPress: snippets essenciais, mostro alguns códigos que fazem sentido no tema filho ou em um plugin de snippets porque são hooks do WordPress. A situação é diferente quando o trecho contém uma credencial: o hook pode ficar no código; já o segredo, não.

O wp-config.php é melhor, mas não é um cofre

Mesmo no wp-config.php, uma chave inserida diretamente continuará armazenada como texto legível no servidor. Uma pessoa com acesso aos arquivos, a um backup exposto ou à conta de hospedagem ainda poderá encontrá-la.

Em uma hospedagem WordPress gerenciada, como a Hostinger Cloud, declarar a chave no wp-config.php pode ser a alternativa prática quando o provedor não oferece uma forma documentada de configurar variáveis de ambiente persistentes para o PHP. Nesse cenário, proteja o acesso à hospedagem e aos backups e limite a chave no serviço de origem.

Portanto, migrar do functions.php para o wp-config.php representa uma melhoria real, mas não resolve tudo sozinho.

Onde armazenar credenciais no WordPress?

Em sites WordPress de clientes pequenos e médios, normalmente não precisamos criar uma estrutura corporativa de segurança. O mais importante é evitar que as credenciais apareçam no código da página, em arquivos do tema ou em scripts que possam ser compartilhados.

A opção mais adequada depende de como a integração foi criada:

  1. Integrações feitas por plugins: quando usamos um plugin confiável, como o WP Mail SMTP, uma solução de login social ou um gateway de pagamento, normalmente inserimos a credencial na própria tela de configuração. Essa costuma ser a alternativa mais prática para o cliente.
  2. Integrações personalizadas: em uma hospedagem gerenciada, podemos declarar a credencial no wp-config.php. Se o provedor oferecer uma forma documentada de criar variáveis de ambiente persistentes para o PHP, o arquivo pode apenas ler esse valor. Em ambos os casos, a lógica da integração deve ficar fora do arquivo de configuração.
  3. Projetos com infraestrutura mais avançada: um serviço como o Secret Manager pode guardar chaves de API, tokens e senhas, inclusive de outros fornecedores. Ele faz mais sentido quando a aplicação já possui uma forma segura de acessá-lo. Para chaves JSON de contas de serviço do Google, a recomendação é evitar a chave permanente sempre que possível, em vez de apenas transferi-la para o cofre.
O FluentSMTP permite armazenar as credenciais do Amazon SES criptografadas no banco de dados ou defini-las no arquivo de configuração do WordPress

Independentemente da opção escolhida, a chave deve ter apenas as permissões necessárias e, sempre que possível, ser limitada aos domínios, endereços IP ou serviços autorizados 🫡

Exemplo prático: uma integração personalizada

Antes de avançarmos, vale reforçar que este exemplo se aplica principalmente a uma integração desenvolvida por você. Quando usamos um plugin confiável, normalmente inserimos a credencial na tela de configuração oferecida pelo próprio plugin.

O que não fazer

Em uma integração personalizada, devemos evitar colocar a chave diretamente no functions.php:

// functions.php — evite armazenar a credencial aqui.
define( 'FREELAB_GOOGLE_API_KEY', 'SUA_CHAVE_AQUI' );

function freelab_integracao_google() {
    // A lógica utiliza a constante definida dentro do tema.
}

O código pode até funcionar, mas a credencial passa a fazer parte do tema e pode acompanhá-lo em arquivos ZIP, repositórios ou compartilhamentos com outros desenvolvedores.

Uma organização bem melhor

Em uma hospedagem WordPress convencional, a alternativa mais prática é declarar a chave no wp-config.php. O trecho deve ficar antes da linha que encerra a edição do arquivo:

// wp-config.php
define( 'FREELAB_GOOGLE_API_KEY', 'SUA_CHAVE_AQUI' );

Essa opção ainda mantém a chave como texto legível no servidor, mas evita que ela fique armazenada dentro do tema.

Uma forma mais avançada

Se a hospedagem oferecer uma forma documentada de configurar variáveis de ambiente persistentes para o PHP, podemos dar um passo adicional: o valor fica no servidor e o wp-config.php apenas o disponibiliza ao WordPress.

// wp-config.php
$freelab_google_api_key = getenv( 'FREELAB_GOOGLE_API_KEY' );

if ( false !== $freelab_google_api_key && '' !== $freelab_google_api_key ) {
    define( 'FREELAB_GOOGLE_API_KEY', $freelab_google_api_key );
}

unset( $freelab_google_api_key );

A lógica da integração deve permanecer em um plugin próprio. Esse código utiliza a constante esperada, mas não contém o valor real da chave:

function freelab_consultar_google() {
    if (
        ! defined( 'FREELAB_GOOGLE_API_KEY' ) ||
        '' === FREELAB_GOOGLE_API_KEY
    ) {
        return new WP_Error(
            'google_api_key_missing',
            'A integração não está configurada.'
        );
    }

    return wp_remote_get(
        'https://example.googleapis.com/v1/recurso',
        array(
            'headers' => array(
                'x-goog-api-key' => FREELAB_GOOGLE_API_KEY,
            ),
            'timeout' => 15,
        )
    );
}

O endereço utilizado no exemplo é ilustrativo e deve ser substituído pelo endpoint da API escolhida. Nas APIs do Google que aceitam esse formato, o cabeçalho x-goog-api-key evita que a chave seja incluída diretamente na URL. Outros serviços podem exigir formatos diferentes, como o cabeçalho Authorization.

Perceba também que a mensagem de erro informa apenas que a integração não está configurada. Ela não revela o valor da credencial.

E quando a chave precisa chegar ao navegador?

O exemplo anterior representa uma chamada realizada pelo servidor. A Places API funciona de outra maneira: a chave precisa chegar ao navegador para que o mapa seja carregado.

Nesse caso, armazená-la no wp-config.php evita que o valor fique gravado no tema, mas não torna a chave secreta. Um visitante ainda poderá encontrá-la no código-fonte ou nas requisições da página.

A proteção deve ser configurada no Google Cloud, limitando a chave aos domínios autorizados e somente às APIs necessárias. Também é recomendável configurar cotas, acompanhar o consumo e utilizar chaves diferentes para produção, staging, aplicativos móveis e integrações executadas no servidor.

Controle as permissões e saiba agir em caso de vazamento

Não basta armazenar uma credencial em um local protegido. Ela também deve possuir somente as permissões necessárias para executar a integração.

Se um site precisa apenas consultar uma planilha, por exemplo, não faz sentido conceder acesso completo à conta ou ao projeto do serviço.

Sempre que possível, evite utilizar a mesma conta de serviço ou chave em vários clientes e projetos. Manter credenciais separadas facilita identificar onde elas são usadas e permite desativar uma integração sem afetar todas as outras.

Também vale manter um controle simples contendo:

  • O site, plugin ou serviço que utiliza cada credencial;
  • Onde ela está armazenada;
  • Quais permissões foram concedidas;
  • Quem é o responsável pela integração;
  • Quando ela foi utilizada ou revisada pela última vez.

Quando o serviço puder gerar cobranças, configure alertas de orçamento e acompanhe o consumo. Um aumento inesperado nas requisições ou no faturamento pode indicar que uma chave está sendo utilizada indevidamente.

Se uma credencial aparecer em um repositório público, log, e-mail, chamado de suporte ou arquivo acessível pela web, considere-a comprometida. Crie uma substituta, atualize e teste a integração, desative a antiga e revise os registros de uso e faturamento.

No WordPress, revise os usuários administrativos, plugins de gerenciamento de arquivos, backups, telas de diagnóstico, repositórios do tema filho e o acesso ao wp-config.php. A documentação oficial recomenda proteger as permissões desse arquivo, mas a configuração correta dependerá da hospedagem. Por isso, não aplique permissões aleatórias sem validar o ambiente.

Essa revisão pode fazer parte da manutenção técnica do projeto. No artigo Manutenção de sites WordPress: como fazer e por que ela é essencial, explico por que segurança, atualizações e monitoramento devem ser tratados como uma rotina, e não apenas quando um problema já apareceu.

Conclusão

A principal lição é simples: fazer a integração funcionar é apenas a primeira etapa. Também precisamos saber onde a credencial está armazenada, quais permissões ela possui e quem perceberá um uso anormal.

Entre colocar uma chave no functions.php e no wp-config.php, escolha o wp-config.php. Em uma hospedagem WordPress convencional, declarar o valor diretamente nesse arquivo é uma solução prática quando não existe um recurso documentado para variáveis de ambiente persistentes no PHP. Se a hospedagem oferecer esse recurso, o arquivo pode apenas ler o valor.

Em projetos mais avançados, um gerenciador de segredos pode ajudar com chaves de API, tokens e senhas. Já a lógica da integração deve ficar em um plugin quando precisa funcionar independentemente do tema. Por fim, limite cada credencial ao mínimo necessário e acompanhe o consumo.

Eu já utilizei soluções mais simples no início e entendo por que elas são tentadoras: são rápidas e resolvem o problema imediato. A evolução profissional acontece quando transformamos esse código que “funciona” em uma solução que também pode ser mantida e entregue com segurança ao cliente 😉

Perguntas frequentes

Sim. Em uma hospedagem WordPress convencional, o wp-config.php é uma solução aceitável e muito melhor do que guardar a chave no tema. Proteja o arquivo e aplique restrições à credencial.

Se não houver uma opção documentada para variáveis de ambiente persistentes no PHP, declare a chave no wp-config.php. Mantenha-a fora do tema e do repositório, proteja a conta de hospedagem e limite a chave no serviço de origem.

Não completamente. A chave precisa chegar ao navegador para carregar o mapa. Restrinja-a aos domínios autorizados e somente à Places API, além de configurar cotas e acompanhar o uso.

A chave de API identifica o projeto que chama um serviço. A conta de serviço representa a própria aplicação e possui permissões específicas. Por isso, um arquivo JSON de conta de serviço costuma exigir mais cuidado.

Em um plugin próprio, quando a integração precisa continuar funcionando após uma troca de tema. Use o tema filho apenas para código realmente ligado à aparência ou ao comportamento do tema. O wp-config.php deve apenas disponibilizar a configuração.

Não. Em um site comum, a configuração do plugin ou o wp-config.php pode ser suficiente. O Secret Manager faz mais sentido em projetos com infraestrutura e controle de acesso mais avançados.

Crie uma nova chave, atualize e teste a integração, desative a antiga e revise os registros de uso e cobrança. Apagar o valor do arquivo atual não basta se existirem cópias em backups, logs ou no histórico do Git.

Não existe um prazo único. Os 30 dias citados no e-mail que recebi servem para revisar chaves inativas, não para obrigar a troca de todas elas. Substitua uma credencial imediatamente se houver suspeita de exposição e revise periodicamente as que continuam em uso.

VOCÊ PODERÁ GOSTAR TAMBÉM

Posts Recentes