TL;DR
Scopes OAuth 2.0 são strings de permissão que definem o que um token de acesso pode fazer. Use o formato recurso:ação como pets:read ou orders:write. Solicite scopes durante a autorização, valide-os nos endpoints da API. A Modern PetstoreAPI implementa scopes para acesso de leitura/escrita a pets, pedidos e dados de usuários.
Introdução
Um aplicativo de terceiros deseja ler o inventário da sua pet shop. Ele deveria ter acesso total para criar pedidos, excluir pets e gerenciar usuários? Não. Ele deveria apenas ler o inventário.
Os scopes OAuth 2.0 resolvem isso. Scopes definem quais permissões um token de acesso possui. O aplicativo solicita o scope inventory:read. Sua API valida se o token possui este scope antes de retornar os dados.
Modern PetstoreAPI implementa scopes granulares para todos os recursos: pets, pedidos, inventário e usuários.
Se você está testando APIs OAuth, o Apidog ajuda a testar a validação de scopes e os fluxos de autorização.
O Que São Scopes OAuth 2.0?
Scopes são strings de permissão incluídas nos tokens de acesso OAuth.
Formato do Scope
pets:read - Ler dados de pets
pets:write - Criar/atualizar pets
orders:read - Ler pedidos
orders:write - Criar pedidos
admin:all - Acesso total de administrador
Scope no Fluxo OAuth
1. Solicitação de Autorização:
GET /oauth/authorize?
client_id=app123&
scope=pets:read orders:read&
redirect_uri=https://app.com/callback
2. Consentimento do Usuário:
O aplicativo "PetFinder" quer:
- Ler seus pets
- Ler seus pedidos
[Permitir] [Negar]
3. Token de Acesso:
{
"access_token": "eyJhbGc...",
"scope": "pets:read orders:read",
"expires_in": 3600
}
4. Solicitação da API:
GET /v1/pets
Authorization: Bearer eyJhbGc...
200 OK (scope validado)
Como os Scopes Funcionam
Token Contém Scopes
O token de acesso inclui os scopes concedidos:
// JWT Decodificado
{
"sub": "user-456",
"scope": "pets:read orders:read",
"exp": 1710331200
}
API Valida Scopes
app.get('/v1/pets', requireScope('pets:read'), async (req, res) => {
const pets = await getPets();
res.json(pets);
});
app.post('/v1/pets', requireScope('pets:write'), async (req, res) => {
const pet = await createPet(req.body);
res.status(201).json(pet);
});
function requireScope(requiredScope) {
return (req, res, next) => {
const token = extractToken(req);
const decoded = verifyToken(token);
if (!decoded.scope.includes(requiredScope)) {
return res.status(403).json({
error: 'insufficient_scope',
message: `Requer scope: ${requiredScope}`
});
}
next();
};
}
Projetando Scopes
Convenções de Nomenclatura de Scopes
Padrão Recurso:Ação:
pets:read
pets:write
orders:read
orders:write
users:read
users:write
Scopes Granulares:
pets:read
pets:create
pets:update
pets:delete
Scopes Curinga (Wildcard):
pets:* - Todas as operações de pet
*:read - Ler todos os recursos
admin:* - Acesso total de administrador
Hierarquia de Scopes
admin:all
├── pets:*
│ ├── pets:read
│ ├── pets:write
│ └── pets:delete
├── orders:*
│ ├── orders:read
│ └── orders:write
└── users:*
├── users:read
└── users:write
Implementando a Validação de Scopes
Abordagem de Middleware
function requireScopes(...requiredScopes) {
return (req, res, next) => {
const token = extractToken(req);
const decoded = verifyToken(token);
const tokenScopes = decoded.scope.split(' ');
const hasAllScopes = requiredScopes.every(scope =>
tokenScopes.includes(scope) || tokenScopes.includes('admin:all')
);
if (!hasAllScopes) {
return res.status(403).json({
error: 'insufficient_scope',
required: requiredScopes,
provided: tokenScopes
});
}
req.user = decoded;
next();
};
}
// Uso
app.get('/v1/pets', requireScopes('pets:read'), getPets);
app.post('/v1/pets', requireScopes('pets:write'), createPet);
app.delete('/v1/pets/:id', requireScopes('pets:delete'), deletePet);
Abordagem de Decorator (TypeScript)
function RequireScopes(...scopes: string[]) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const req = args[0];
const res = args[1];
const token = extractToken(req);
const decoded = verifyToken(token);
if (!hasScopes(decoded.scope, scopes)) {
return res.status(403).json({ error: 'insufficient_scope' });
}
return originalMethod.apply(this, args);
};
};
}
// Uso
class PetsController {
@RequireScopes('pets:read')
async getPets(req, res) {
const pets = await this.petService.findAll();
res.json(pets);
}
@RequireScopes('pets:write')
async createPet(req, res) {
const pet = await this.petService.create(req.body);
res.status(201).json(pet);
}
}
Como a Modern PetstoreAPI Usa Scopes
Scopes Disponíveis
pets:read - Ler dados de pets
pets:write - Criar/atualizar pets
pets:delete - Excluir pets
orders:read - Ler pedidos
orders:write - Criar pedidos
inventory:read - Ler inventário
inventory:write - Atualizar inventário
users:read - Ler perfil de usuário
users:write - Atualizar perfil de usuário
admin:all - Acesso total
Validação de Scope
GET /v1/pets
Authorization: Bearer token_com_pets:read
200 OK
POST /v1/pets
Authorization: Bearer token_com_pets:read
403 Forbidden
{
"error": "insufficient_scope",
"required": ["pets:write"],
"provided": ["pets:read"]
}
Consulte a documentação OAuth da Modern PetstoreAPI.
Testando Scopes com Apidog
Apidog suporta o teste de scopes OAuth:
- Configure a autenticação OAuth 2.0
- Solicite scopes específicos
- Teste endpoints com diferentes scopes
- Valide respostas 403 para scopes insuficientes
Melhores Práticas
1. Use scopes granulares - pets:read e não read_all
2. Siga as convenções de nomenclatura - formato recurso:ação
3. Documente todos os scopes - Liste na documentação da API
4. Valide a cada solicitação - Não confie no cliente
5. Retorne erros claros - Mostre os scopes necessários versus os fornecidos
6. Use o menor privilégio - Solicite o mínimo de scopes necessários
Conclusão
Os scopes OAuth 2.0 fornecem controle de acesso granular. Use o formato recurso:ação, valide a cada solicitação e documente todos os scopes. A Modern PetstoreAPI demonstra uma implementação de scopes pronta para produção.
FAQ
Qual a diferença entre scopes e funções (roles)?
Scopes são permissões para tokens de acesso. Funções são grupos de usuários com permissões atribuídas.
É possível ter múltiplos scopes?
Sim, separe com espaços: pets:read orders:read users:write
Como revogar scopes?
Revogue o token de acesso ou emita um novo token com scopes diferentes.
Os scopes devem estar no JWT?
Sim, inclua na `claim` scope para validação stateless.
Quão granulares devem ser os scopes?
Equilibre a granularidade com a usabilidade. pets:read e pets:write geralmente são suficientes.
