Diferenca entre Autenticacao e Autorizacao
Primeiro, vamos organizar dois conceitos que sao facilmente confundidos.
- Autenticacao (Authentication): “Quem e voce?” - Verificar a identidade do usuario
- Autorizacao (Authorization): “O que voce pode fazer?” - Verificar permissoes de acesso
flowchart LR
A[Login] --> B[Autenticacao<br/>Verificacao de identidade por ID/Senha]
B --> C[Operacao]
C --> D[Autorizacao<br/>Verificar se tem permissao para esta operacao]
Comparacao de Metodos de Autenticacao
| Metodo | Gerenciamento de Estado | Caso Adequado |
|---|
| Autenticacao por Sessao | Lado do servidor | Apps Web tradicionais |
| Autenticacao por Token (JWT) | Lado do cliente | SPA, Apps mobile |
| OAuth 2.0 | Servico externo | Autenticacao de terceiros, Integracao de API |
Autenticacao por Sessao
Funcionamento
sequenceDiagram
participant C as Cliente
participant S as Servidor
participant Store as Armazenamento de Sessao
rect rgb(240, 248, 255)
Note over C,Store: 1. Login
C->>S: Envio de ID/Senha
S->>S: Autenticacao
S->>Store: Geracao e armazenamento de ID de sessao
S->>C: Set-Cookie: session_id=abc123
end
rect rgb(245, 255, 245)
Note over C,Store: 2. Requisicoes subsequentes
C->>S: Cookie: session_id=abc123
S->>Store: Validacao do ID de sessao
Store->>S: Resultado da validacao
end
Exemplo de Implementacao
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 });
}
});
Vantagens e Desvantagens
| Vantagens | Desvantagens |
|---|
| Facil invalidar sessao | Necessario gerenciamento de estado no servidor |
| Facil controle de seguranca | Necessario compartilhamento de sessao em ambiente distribuido |
| Implementacao simples | Compatibilidade ruim com apps mobile |
Autenticacao por Token (JWT)
Funcionamento
sequenceDiagram
participant C as Cliente
participant S as Servidor
rect rgb(240, 248, 255)
Note over C,S: 1. Login
C->>S: Envio de ID/Senha
S->>S: Autenticacao → Geracao de JWT (com assinatura)
S->>C: { "token": "eyJhbG..." }
end
rect rgb(245, 255, 245)
Note over C,S: 2. Requisicoes subsequentes
C->>S: Authorization: Bearer eyJhbG...
S->>S: Validacao da assinatura do JWT (sem acesso ao armazenamento)
end
Estrutura do JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. ← Header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6... ← Payload
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ← Assinatura
Header (decodificado em Base64):
{ "alg": "HS256", "typ": "JWT" }
Payload (decodificado em Base64):
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516325422
}
Exemplo de Implementacao
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["Tempo de expiracao dos tokens"]
AT["Access Token<br/>Curta duracao (15min a 1 hora)"]
RT["Refresh Token<br/>Longa duracao (7 a 30 dias), armazenado com seguranca"]
end
A[Access Token expirado] --> B[Obter novo Access Token usando Refresh Token]
B --> C{Refresh Token tambem expirou?}
C -->|Sim| D[Re-login]
C -->|Nao| E[Continuar com novo Access Token]
Vantagens e Desvantagens
| Vantagens | Desvantagens |
|---|
| Stateless, facil escalar | Dificil invalidar token |
| Adequado para sistemas distribuidos | Tamanho do token e grande |
| Adequado para mobile/SPA | Payload nao e criptografado |
OAuth 2.0
Visao Geral
E um mecanismo de autenticacao e autorizacao usando servicos de terceiros (Google, GitHub, etc.).
sequenceDiagram
participant U as Usuario
participant A as Sua Aplicacao<br/>(Client)
participant AS as Servidor de Autorizacao<br/>(Google, etc.)
U->>A: 1. Clique no botao de login
A->>AS: 2. Solicitacao de autorizacao
AS->>U: 3. Tela de login
U->>AS: 4. Autenticacao e consentimento
AS->>A: 5. Codigo de autorizacao
A->>AS: 6. Solicitacao de token
AS->>A: 7. Access Token
A->>U: 8. Login concluido
Exemplo de Implementacao (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 | Apps Web (mais comum) |
| PKCE | SPA, Apps mobile |
| Client Credentials | Comunicacao entre servidores |
| Device Code | Dispositivos com entrada limitada como Smart TVs |
Como Escolher o Metodo de Autenticacao
flowchart LR
subgraph Apps["Tipo de Aplicacao"]
A1["App Web tradicional<br/>(Server-side rendering)"]
A2["SPA + API"]
A3["App Mobile"]
A4["Login de terceiros<br/>(Login com Google, etc.)"]
A5["Comunicacao entre microsservicos"]
end
subgraph Auth["Metodo de Autenticacao Recomendado"]
B1["Autenticacao por Sessao"]
B2["JWT<br/>(Access Token curto + Refresh Token)"]
B3["JWT ou OAuth 2.0 (PKCE)"]
B4["OAuth 2.0 / OpenID Connect"]
B5["JWT ou OAuth 2.0<br/>(Client Credentials)"]
end
A1 --> B1
A2 --> B2
A3 --> B3
A4 --> B4
A5 --> B5
Resumo
A escolha do metodo de autenticacao varia de acordo com o tipo de aplicacao, requisitos de seguranca e requisitos de escalabilidade. A autenticacao por sessao e simples de implementar e facil de controlar, enquanto JWT e stateless e facil de escalar. OAuth 2.0 e ideal para autenticacao de terceiros e integracao de APIs. Entenda as caracteristicas de cada um e escolha o metodo apropriado.
← Voltar para a lista