Definicion
Cuando instalas una nueva app en tu móvil, te pide permisos: acceso a tu cámara, ubicación, contactos. Puedes conceder algunos y denegar otros. Los scopes de OAuth funcionan exactamente igual para APIs - permiten a usuarios y aplicaciones solicitar permisos específicos en lugar de acceso todo o nada a una cuenta.
Sin scopes, la autorización sería binaria: o una app tiene acceso completo a tu cuenta, o no tiene ningún acceso. Eso es peligroso. Una simple app de impresión de fotos no debería necesitar acceso a tu email, contactos y datos financieros solo para imprimir algunas fotos. Los scopes resuelven esto permitiéndote especificar exactamente qué permisos necesita una aplicación. Cuando haces “Iniciar sesión con Google” en una nueva app, esa pantalla de consentimiento que lista “Ver tu dirección de email” y “Ver tu perfil” te está mostrando los scopes que se están solicitando.
La parte ingeniosa es que los scopes funcionan a múltiples niveles. Primero, la aplicación solicita scopes específicos. Luego, el usuario los aprueba (o deniega). Finalmente, el access token emitido está limitado solo a esos scopes aprobados. Cuando la app intenta usar el token para acceder a una API, el servidor verifica si los scopes del token permiten esa acción específica. Un token con scope read:photos no puede eliminar fotos, aunque la API soporte eliminación. Este principio de mínimo privilegio reduce dramáticamente el riesgo si un token se ve comprometido.
Ejemplo
Flujos de “Iniciar sesión con” de Google: Cuando un sitio web te pide iniciar sesión con Google, solicita scopes específicos. Un login simple podría solo pedir profile y email. Una app de calendario también solicitaría calendar.readonly o calendar.events. Google te muestra exactamente qué acceso estás concediendo.
Apps OAuth de GitHub: Cuando autorizas una app de GitHub, ves scopes como repo, user:email, read:org. Una herramienta de CI/CD podría necesitar repo para leer tu código, pero una app de notificaciones solo necesita notifications - no requiere acceso al código.
Integraciones de Spotify: Las apps de gestión de playlists solicitan playlist-modify-public y playlist-modify-private. Una app de visualización de música solo necesita user-read-playback-state - no puede modificar tus playlists, solo ver qué se está reproduciendo.
Dispositivos de hogar inteligente: Cuando vinculas Alexa a tu termostato inteligente, el scope podría ser thermostat:read y thermostat:write para control de temperatura, pero no camera:view si Alexa no necesita ver tus cámaras de seguridad.
Analogia
Los Permisos de Apps del Smartphone: Esta es la analogía más directa porque funciona idénticamente. Así como tu app de fotos pide acceso a la cámara pero no a tus contactos, los scopes de OAuth permiten a las aplicaciones solicitar solo los permisos de API que necesitan. Y al igual que puedes revocar permisos de apps después, puedes revocar scopes de OAuth.
La Tarjeta de Acceso del Edificio de Apartamentos: Tu tarjeta de acceso podría abrir tu apartamento, el gimnasio y el parking - pero no otros apartamentos o el cuarto de mantenimiento. La tarjeta de cada inquilino está programada con accesos específicos. Los tokens OAuth con scopes funcionan idénticamente - cada token está programado con permisos específicos.
Las Categorías de Carné de Biblioteca: Algunos carnés de biblioteca solo te dejan tomar prestados libros. Otros también dan acceso a recursos digitales, salas de reuniones o colecciones especiales. El carné parece igual, pero los permisos codificados difieren. Los tokens OAuth similarmente parecen iguales pero llevan diferentes scopes.
Los Niveles de Acceso de Empleados: En una empresa, diferentes empleados tienen diferentes accesos al sistema. Un contable puede acceder a sistemas financieros pero no a repositorios de ingeniería. Un desarrollador tiene acceso al código pero no puede aprobar gastos. Los scopes crean estos niveles de acceso para APIs.
Code Example
// Solicitar scopes específicos durante autorización
const authUrl = new URL('https://oauth.provider.com/authorize');
authUrl.searchParams.append('response_type', 'code');
authUrl.searchParams.append('client_id', 'your_client_id');
authUrl.searchParams.append('redirect_uri', 'https://yourapp.com/callback');
// Solicitar múltiples scopes (separados por espacio)
authUrl.searchParams.append('scope', 'read:user read:email write:posts');
authUrl.searchParams.append('state', generateRandomState());
// El endpoint de token devuelve los scopes concedidos
const tokenResponse = await fetch('https://oauth.provider.com/token', {
method: 'POST',
body: tokenParams
});
const { access_token, scope } = await tokenResponse.json();
console.log('Scopes concedidos:', scope); // Puede diferir de los solicitados
// Validar scopes en el servidor API
function requireScope(requiredScope) {
return (req, res, next) => {
const token = extractToken(req);
const tokenScopes = token.scope.split(' ');
if (!tokenScopes.includes(requiredScope)) {
return res.status(403).json({
error: 'insufficient_scope',
error_description: `Requiere scope: ${requiredScope}`
});
}
next();
};
}
// Ruta protegida con requisito de scope
app.delete('/posts/:id', requireScope('delete:posts'), (req, res) => {
// Solo tokens con scope delete:posts pueden acceder
});
// Patrones comunes de scopes
// read:resource, write:resource, delete:resource
// resource.read, resource.write, resource.delete
// user:email, user:profile, repo:public, repo:private
Diagrama
flowchart TD
subgraph Request["1. Solicitud de Autorizacion"]
A[App solicita scopes:
read write delete]
end
subgraph Consent["2. Pantalla de Consentimiento"]
B["Esta app quiere:
- Leer tus datos
- Escribir tus datos
- Eliminar tus datos"]
C{Decision del Usuario}
end
subgraph Approval["3. Usuario Aprueba Subconjunto"]
D["Usuario concede solo:
read write
(deniega delete)"]
end
subgraph Token["4. Token Emitido"]
E["Access Token creado con:
scope = 'read write'"]
end
subgraph API["5. Control de Acceso API"]
F["GET /data
Requiere: read"]
G["POST /data
Requiere: write"]
H["DELETE /data
Requiere: delete"]
I{Verificar Scopes del Token}
end
A --> B
B --> C
C -->|Aprobacion Parcial| D
C -->|Denegar Todo| J[No se Emite Token]
D --> E
E --> I
I -->|Tiene 'read'| F
I -->|Tiene 'write'| G
I -->|Falta 'delete'| K["403 Forbidden
insufficient_scope"]
F --> L[200 OK]
G --> L
H --> I
style K fill:#ffcccc
style L fill:#ccffcc
style D fill:#ffffcc
Notas de Seguridad
CRÍTICO - …
Configuración y Validación:
- Seguir principio de mínimo privilegio: solicitar solo scopes necesarios.
- Validar scopes en cada petición de API, no solo en emisión de token.
- El usuario debe consentir explícitamente los scopes (UI clara mostrando qué acceso se otorga).
- Los scopes otorgados pueden diferir de los solicitados (el usuario puede denegar algunos).
- Implementar jerarquía de scopes cuidadosamente (read no debe implicar write).
- Usar scopes granulares (read:user:email mejor que user:*).
Monitoreo y Protección:
- Documentar todos los scopes disponibles claramente.
- Los scopes no reemplazan verificaciones de autorización adecuadas (verificar que el usuario posee el recurso).
- Considerar scopes con límite de tiempo para operaciones sensibles.
- Implementar validación de scopes consistentemente en todos los endpoints.
- Auditar uso de scopes.
- Permitir a usuarios revisar y revocar scopes otorgados.