Diferencia entre Autenticacion y Autorizacion
Primero, vamos a clarificar dos conceptos que a menudo se confunden.
- Autenticacion (Authentication): “Quien eres?” - Verificar la identidad del usuario
- Autorizacion (Authorization): “Que puedes hacer?” - Verificar permisos de acceso
flowchart LR
A[Login] --> B[Autenticacion<br/>Verificar identidad con ID/Contrasena]
B --> C[Operacion]
C --> D[Autorizacion<br/>Verificar si tiene permiso para esta operacion]
Comparacion de Metodos de Autenticacion
| Metodo | Gestion de Estado | Caso Adecuado |
|---|
| Autenticacion por Sesion | Lado del servidor | Aplicaciones web tradicionales |
| Autenticacion por Token (JWT) | Lado del cliente | SPA, aplicaciones moviles |
| OAuth 2.0 | Servicio externo | Autenticacion de terceros, integracion de API |
Autenticacion por Sesion
Funcionamiento
sequenceDiagram
participant C as Cliente
participant S as Servidor
participant Store as Almacen de Sesiones
rect rgb(240, 248, 255)
Note over C,Store: 1. Login
C->>S: Enviar ID/Contrasena
S->>S: Autenticar
S->>Store: Generar y guardar ID de sesion
S->>C: Set-Cookie: session_id=abc123
end
rect rgb(245, 255, 245)
Note over C,Store: 2. Solicitudes posteriores
C->>S: Cookie: session_id=abc123
S->>Store: Verificar ID de sesion
Store->>S: Resultado de verificacion
end
Ejemplo de Implementacion
const session = require('express-session');
const RedisStore = require('connect-redis').default;
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000
}
}));
app.post('/login', async (req, res) => {
const user = await authenticate(req.body);
if (user) {
req.session.userId = user.id;
res.json({ success: true });
}
});
Ventajas y Desventajas
| Ventajas | Desventajas |
|---|
| Facil invalidar sesiones | Requiere gestion de estado en el servidor |
| Facil control de seguridad | Requiere compartir sesiones en entornos distribuidos |
| Implementacion simple | Mala compatibilidad con aplicaciones moviles |
Autenticacion por Token (JWT)
Funcionamiento
sequenceDiagram
participant C as Cliente
participant S as Servidor
rect rgb(240, 248, 255)
Note over C,S: 1. Login
C->>S: Enviar ID/Contrasena
S->>S: Autenticar → Generar JWT (firmado)
S->>C: { "token": "eyJhbG..." }
end
rect rgb(245, 255, 245)
Note over C,S: 2. Solicitudes posteriores
C->>S: Authorization: Bearer eyJhbG...
S->>S: Verificar firma del JWT (sin acceso al almacen)
end
Estructura del JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. ← Header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6... ← Payload
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ← Firma
Header (decodificado Base64):
{ "alg": "HS256", "typ": "JWT" }
Payload (decodificado Base64):
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516325422
}
Ejemplo de Implementacion
const jwt = require('jsonwebtoken');
app.post('/login', async (req, res) => {
const user = await authenticate(req.body);
if (user) {
const token = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
res.json({ token });
}
});
function authMiddleware(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
}
Refresh Token
flowchart TD
subgraph Tokens["Tiempo de expiracion de tokens"]
AT["Access Token<br/>Corta duracion (15 min - 1 hora)"]
RT["Refresh Token<br/>Larga duracion (7 - 30 dias), almacenado de forma segura"]
end
A[Access Token expirado] --> B[Obtener nuevo Access Token con Refresh Token]
B --> C{Refresh Token tambien expirado?}
C -->|Si| D[Re-login]
C -->|No| E[Continuar con nuevo Access Token]
Ventajas y Desventajas
| Ventajas | Desventajas |
|---|
| Sin estado, facil de escalar | Dificil invalidar tokens |
| Adecuado para sistemas distribuidos | Tamano del token grande |
| Adecuado para movil/SPA | El payload no esta encriptado |
OAuth 2.0
Descripcion General
Es un mecanismo de autenticacion y autorizacion que utiliza servicios de terceros (Google, GitHub, etc.).
sequenceDiagram
participant U as Usuario
participant A as Tu Aplicacion<br/>(Client)
participant AS as Servidor de Autorizacion<br/>(Google, etc.)
U->>A: 1. Clic en boton de login
A->>AS: 2. Solicitud de autorizacion
AS->>U: 3. Pantalla de login
U->>AS: 4. Autenticacion y consentimiento
AS->>A: 5. Codigo de autorizacion
A->>AS: 6. Solicitud de token
AS->>A: 7. Access token
A->>U: 8. Login completado
Ejemplo de Implementacion (Authorization Code Flow)
app.get('/auth/google', (req, res) => {
const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth');
authUrl.searchParams.set('client_id', process.env.GOOGLE_CLIENT_ID);
authUrl.searchParams.set('redirect_uri', 'https://myapp.com/callback');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'openid email profile');
authUrl.searchParams.set('state', generateState());
res.redirect(authUrl.toString());
});
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
verifyState(state);
const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
body: new URLSearchParams({
client_id: process.env.GOOGLE_CLIENT_ID,
client_secret: process.env.GOOGLE_CLIENT_SECRET,
code,
grant_type: 'authorization_code',
redirect_uri: 'https://myapp.com/callback'
})
});
const { access_token, id_token } = await tokenResponse.json();
});
Tipos de Grant
| Tipo de Grant | Uso |
|---|
| Authorization Code | Aplicaciones web (mas comun) |
| PKCE | SPA, aplicaciones moviles |
| Client Credentials | Comunicacion entre servidores |
| Device Code | Dispositivos con entrada limitada como Smart TV |
Como Elegir el Metodo de Autenticacion
flowchart LR
subgraph Apps["Tipo de Aplicacion"]
A1["Aplicacion web tradicional<br/>(Server-side rendering)"]
A2["SPA + API"]
A3["Aplicacion movil"]
A4["Login de terceros<br/>(Login con Google, etc.)"]
A5["Comunicacion entre microservicios"]
end
subgraph Auth["Metodo de Autenticacion Recomendado"]
B1["Autenticacion por Sesion"]
B2["JWT<br/>(Access Token de corta duracion + Refresh Token)"]
B3["JWT o OAuth 2.0 (PKCE)"]
B4["OAuth 2.0 / OpenID Connect"]
B5["JWT o OAuth 2.0<br/>(Client Credentials)"]
end
A1 --> B1
A2 --> B2
A3 --> B3
A4 --> B4
A5 --> B5
Resumen
La eleccion del metodo de autenticacion depende del tipo de aplicacion, requisitos de seguridad y requisitos de escalabilidad. La autenticacion por sesion es simple de implementar y facil de controlar, mientras que JWT es sin estado y facil de escalar. OAuth 2.0 es optimo para autenticacion de terceros e integracion de API. Entendamos las caracteristicas de cada uno y elijamos el metodo apropiado.
← Volver a la lista