# Seguranca de API REST no Symfony 2026: OAuth2, Rate Limiting e Perguntas de Entrevista > Guia completo sobre seguranca de API REST no Symfony com OAuth2, rate limiting, JWT e Voters. Inclui perguntas de entrevista tecnica. - Published: 2026-09-14 - Updated: 2026-09-14 - Author: Anthony Fillion-Maillet - Reading time: 5 min --- A seguranca de APIs REST no Symfony requer uma abordagem em camadas que combina autenticacao, autorizacao e controle de trafego. O Symfony 7.3 introduz suporte nativo para introspection de tokens OAuth2 via RFC 7662, enquanto o componente RateLimiter oferece protecao integrada contra abusos. > **Tres camadas de seguranca para APIs Symfony** > > Uma API Symfony pronta para producao precisa de tres defesas: autenticacao (quem esta chamando), autorizacao (o que pode acessar) e rate limiting (com que frequencia). A ausencia de qualquer camada expoe a aplicacao a credential stuffing, exfiltracao de dados ou negacao de servico. ## Introspection de Tokens OAuth2 no Symfony 7.3 O Symfony 7.3 adiciona suporte nativo para [introspection de tokens OAuth2 (RFC 7662)](https://datatracker.ietf.org/doc/html/rfc7662). Essa funcionalidade valida tokens de acesso consultando diretamente o servidor de autorizacao, eliminando a necessidade de decodificar tokens localmente. Essa abordagem e particularmente util quando o formato do token e opaco ou controlado por um provedor de identidade externo. A configuracao do `AccessTokenHandler` aceita um endpoint de introspection: ```yaml # config/packages/security.yaml security: firewalls: api: pattern: ^/api stateless: true access_token: token_handler: introspection: client_id: '%env(OAUTH_CLIENT_ID)%' client_secret: '%env(OAUTH_CLIENT_SECRET)%' introspection_url: '%env(OAUTH_INTROSPECTION_URL)%' ``` A resposta de introspection contem `active`, `scope`, `client_id` e opcionalmente `username`. O Symfony mapeia esses valores automaticamente para os atributos de seguranca. ```php // src/Controller/Api/ProfileController.php namespace App\Controller\Api; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route('/api/profile', methods: ['GET'])] #[IsGranted('ROLE_USER')] class ProfileController extends AbstractController { public function __invoke(): JsonResponse { // Token ja validado via introspection $user = $this->getUser(); return $this->json([ 'id' => $user->getId(), 'email' => $user->getEmail(), 'scopes' => $user->getRoles(), ]); } } ``` Essa abordagem libera a aplicacao da verificacao de assinaturas JWT. O servidor de autorizacao gerencia a rotacao de chaves, revogacao de tokens e validacao de scopes. ## Implementacao de Rate Limiting com o Componente RateLimiter O [componente RateLimiter](https://symfony.com/doc/current/rate_limiter.html) protege os endpoints contra abusos utilizando algoritmos token bucket ou sliding window. A configuracao e feita no `framework.yaml`: ```yaml # config/packages/framework.yaml framework: rate_limiter: # Limite geral da API: 100 requests por minuto api_limiter: policy: sliding_window limit: 100 interval: '1 minute' # Limite mais restrito para endpoints de autenticacao login_limiter: policy: token_bucket limit: 5 rate: { interval: '1 minute', amount: 5 } ``` O rate limiting e aplicado aos controladores atraves de um event subscriber: ```php // src/EventSubscriber/RateLimitSubscriber.php namespace App\EventSubscriber; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\RateLimiter\RateLimiterFactory; final class RateLimitSubscriber implements EventSubscriberInterface { public function __construct( private readonly RateLimiterFactory $apiLimiter, ) {} public static function getSubscribedEvents(): array { return [KernelEvents::REQUEST => ['onRequest', 10]]; } public function onRequest(RequestEvent $event): void { if (!$event->isMainRequest()) { return; } $request = $event->getRequest(); // Aplicar apenas as rotas de API if (!str_starts_with($request->getPathInfo(), '/api')) { return; } // Usar IP do cliente ou usuario autenticado como chave $key = $request->getClientIp(); $limiter = $this->apiLimiter->create($key); if (!$limiter->consume()->isAccepted()) { throw new TooManyRequestsHttpException(); } } } ``` Para APIs autenticadas, e recomendavel substituir a chave baseada em IP pelo identificador do usuario para evitar que um usuario abusivo afete o trafego legitimo proveniente da mesma rede. ## Validacao JWT Sem Dependencias Externas Quando o servidor de autorizacao emite JWTs com uma chave publica conhecida, o Symfony pode validar tokens localmente usando `OidcUserInfoTokenHandler`: ```yaml # config/packages/security.yaml security: firewalls: api: pattern: ^/api stateless: true access_token: token_handler: oidc_user_info: base_uri: '%env(OIDC_ISSUER)%' claim: email ``` Para JWTs auto-emitidos sem provedor OIDC, o bundle `lexik/jwt-authentication-bundle` oferece uma solucao robusta: ```php // src/Security/JwtTokenAuthenticator.php namespace App\Security; use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; use Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; final class JwtTokenAuthenticator implements AccessTokenHandlerInterface { public function __construct( private readonly JWTTokenManagerInterface $jwtManager, ) {} public function getUserBadgeFrom(string $accessToken): UserBadge { // Decodifica e valida a assinatura automaticamente $payload = $this->jwtManager->parse($accessToken); return new UserBadge($payload['sub']); } } ``` O bundle JWT gerencia a verificacao de assinaturas RS256/ES256, controles de expiracao e validacao do emissor. A chave publica e armazenada em `config/jwt/public.pem` e referenciada em `lexik_jwt_authentication.yaml`. ## Seguranca de Endpoints de API com Voters Os Voters do Symfony fornecem autorizacao granular alem de simples verificacoes de roles. Um padrao comum verifica a propriedade do recurso: ```php // src/Security/Voter/ArticleVoter.php namespace App\Security\Voter; use App\Entity\Article; use App\Entity\User; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; final class ArticleVoter extends Voter { public const EDIT = 'ARTICLE_EDIT'; public const DELETE = 'ARTICLE_DELETE'; protected function supports(string $attribute, mixed $subject): bool { return in_array($attribute, [self::EDIT, self::DELETE], true) && $subject instanceof Article; } protected function voteOnAttribute( string $attribute, mixed $subject, TokenInterface $token ): bool { $user = $token->getUser(); if (!$user instanceof User) { return false; } /** @var Article $article */ $article = $subject; // Admins podem fazer tudo if (in_array('ROLE_ADMIN', $user->getRoles(), true)) { return true; } // Autores podem editar/deletar seus proprios artigos return $article->getAuthor() === $user; } } ``` O uso do voter em controladores e feito assim: ```php #[Route('/api/articles/{id}', methods: ['PUT'])] public function update(Article $article, Request $request): JsonResponse { $this->denyAccessUnlessGranted(ArticleVoter::EDIT, $article); // Logica de atualizacao aqui } ``` Os Voters centralizam a logica de autorizacao e a tornam testavel. Eles aparecem frequentemente nas [perguntas de entrevista Symfony](/technologies/symfony/interview-questions/events-subscribers) sobre o componente de seguranca. ## Vulnerabilidades Comuns de API e Mitigacoes O [OWASP API Security Top 10](https://owasp.org/API-Security/editions/2023/en/0x11-t10/) identifica vulnerabilidades recorrentes em APIs. O Symfony fornece protecao integrada para varias delas: | Vulnerabilidade | Mitigacao Symfony | |---------------|--------------------| | Broken Object Level Authorization | Voters com verificacao de propriedade | | Broken Authentication | Throttling de login, hashing seguro | | Excessive Data Exposure | Grupos de serializacao DTO | | Lack of Rate Limiting | Componente RateLimiter | | Mass Assignment | Validacao de formularios, mapeamento DTO | | Security Misconfiguration | Security checker, variaveis de ambiente | Para protecao contra mass assignment, nunca se deve hidratar entidades diretamente dos dados do request: ```php // src/Dto/CreateArticleDto.php namespace App\Dto; use Symfony\Component\Validator\Constraints as Assert; final class CreateArticleDto { public function __construct( #[Assert\NotBlank] #[Assert\Length(max: 255)] public readonly string $title, #[Assert\NotBlank] public readonly string $content, // Intencionalmente omitido: author, createdAt, status // Esses valores sao definidos pela aplicacao, nao pelo cliente ) {} } ``` A abordagem de whitelist via DTO impede que os clientes definam campos que nao deveriam controlar, como `isAdmin` ou `createdAt`. ## Configuracao CORS para Consumidores de API Os headers Cross-Origin Resource Sharing controlam quais dominios podem chamar a API a partir de navegadores. O bundle `nelmio/cors-bundle` fornece configuracao declarativa: ```yaml # config/packages/nelmio_cors.yaml nelmio_cors: defaults: allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] allow_methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] allow_headers: ['Content-Type', 'Authorization'] max_age: 3600 paths: '^/api/': origin_regex: true allow_origin: ['^https://.*\.example\.com$'] allow_credentials: true ``` Deve-se evitar `allow_origin: ['*']` com `allow_credentials: true`. Essa combinacao expoe a API ao roubo de credenciais por sites maliciosos. Whitelists de dominios explicitas ou padroes regex sao preferiveis. ## Perguntas de Entrevista Tecnica sobre Seguranca de API Symfony Essas perguntas aparecem frequentemente em entrevistas para desenvolvedores Symfony senior. As respostas refletem as capacidades do Symfony 7.3. **P: Como o Symfony gerencia a validacao de tokens de acesso OAuth2?** O Symfony 7.3 suporta tres abordagens: validacao JWT local com verificacao de assinatura, chamadas ao endpoint user info do OIDC e [introspection de token RFC 7662](https://symfony.com/blog/new-in-symfony-7-3-security-improvements). A introspection e adequada para tokens opacos ou cenarios onde a aplicacao nao controla o servidor de autorizacao. O `AccessTokenHandler` abstrai as tres abordagens por tras de uma interface unificada. **P: Qual e a diferenca entre firewalls e access control no Symfony?** Os firewalls definem mecanismos de autenticacao por padrao de URL. As regras de access control definem requisitos de autorizacao apos a autenticacao ser bem-sucedida. Um firewall pode exigir um JWT valido, enquanto access control exige `ROLE_ADMIN` para `/api/admin/*`. Eles operam em sequencia: o firewall autentica, depois o access control autoriza. **P: Como prevenir ataques de forca bruta em um endpoint de login?** O throttling de login integrado do Symfony limita tentativas falhas por nome de usuario e IP. A configuracao de `login_throttling` e feita no firewall: ```yaml security: firewalls: main: login_throttling: max_attempts: 5 interval: '15 minutes' ``` Para autenticacao de API, deve-se combinar com o componente RateLimiter no endpoint de token. Os contadores de tentativas sao armazenados no Redis para implantacoes multi-instancia. **P: Explique os Voters do Symfony e quando usa-los em vez de simples verificacoes de roles.** Os Voters implementam logica de autorizacao complexa que depende do recurso, nao apenas do role do usuario. Deve-se usar Voters quando: o usuario precisa ser proprietario do recurso, o recurso tem uma maquina de estados (rascunho vs publicado), ou a autorizacao depende de regras de negocio (nivel de assinatura). Verificacoes de roles sao suficientes para permissoes estaticas como "apenas admins podem acessar configuracoes". Para mais perguntas de seguranca Symfony, consulte o [guia de preparacao para entrevistas Symfony](/blog/symfony/symfony-interview-questions). ## Construindo uma API Symfony Segura: Pontos-Chave - Configurar introspection de tokens OAuth2 para provedores de identidade externos quando o formato do token e opaco - Aplicar rate limiting no nivel de infraestrutura (reverse proxy) e no nivel de aplicacao (componente RateLimiter) para defesa em profundidade - Usar Voters para autorizacao no nivel de recurso, reservando verificacoes de roles para permissoes estaticas - Mapear dados do request para DTOs com propriedades explicitas para prevenir mass assignment - Armazenar segredos em variaveis de ambiente, nunca em arquivos `config/*.yaml` versionados - Testar regras de seguranca com testes funcionais `WebTestCase` que verificam acessos permitidos e negados - Auditar dependencias com `symfony security:check` em pipelines de CI --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/symfony/symfony-rest-api-security-oauth2-rate-limiting-2026