# JWT

### 📋 **Índice**

1. Fundamentos do JWT
2. Estrutura e Componentes
3. Processo de Encoding
4. Algoritmos de Assinatura
5. Implementação em Linguagens
6. Validação e Decoding
7. Segurança e Boas Práticas
8. Ferramentas e Debug

***

### 🔍 **Fundamentos do JWT**

#### **O que é JWT?**

**JSON Web Token (JWT)** é um padrão aberto (RFC 7519) que define uma forma compacta e autossuficiente de transmitir informações entre partes como um objeto JSON. É amplamente utilizado para autenticação e autorização em APIs e aplicações web modernas.

#### **Características Principais**

```yaml
Características do JWT:
  ✅ Compacto: Pequeno tamanho, ideal para headers HTTP
  ✅ Autossuficiente: Contém todas as informações necessárias
  ✅ Assinado: Garantia de integridade e autenticidade
  ✅ Criptografado: Pode ser criptografado para confidencialidade
  ✅ Auto-contido: Não requer consulta a banco de dados

Casos de Uso:
  - Autenticação de APIs REST
  - Single Sign-On (SSO)
  - Troca segura de informações entre serviços
  - Autorização stateless
  - Mobile apps e SPAs
```

#### **Estrutura do JWT**

```python
#!/usr/bin/env python3
# jwt_structure.py

import json
import base64

class JWTStructure:
    """Análise da estrutura de um JSON Web Token"""
    
    @staticmethod
    def parse_token(token):
        """Parsear token JWT e exibir estrutura"""
        parts = token.split('.')
        
        if len(parts) != 3:
            raise ValueError("Token JWT inválido")
        
        # Decodificar header
        header = json.loads(base64.urlsafe_b64decode(parts[0] + '==').decode())
        
        # Decodificar payload
        payload = json.loads(base64.urlsafe_b64decode(parts[1] + '==').decode())
        
        # Signature permanece codificada
        signature = parts[2]
        
        return {
            'header': header,
            'payload': payload,
            'signature': signature
        }
    
    @staticmethod
    def build_token(header, payload, secret, algorithm='HS256'):
        """Construir token JWT"""
        import jwt
        token = jwt.encode(payload, secret, algorithm=algorithm, headers=header)
        return token

# Exemplo
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

parser = JWTStructure()
parsed = parser.parse_token(token)
print("=== Estrutura JWT ===")
print(f"Header: {json.dumps(parsed['header'], indent=2)}")
print(f"Payload: {json.dumps(parsed['payload'], indent=2)}")
print(f"Signature: {parsed['signature'][:20]}...")
```

***

### 🏗️ **Estrutura e Componentes**

#### **Componentes do JWT**

```yaml
Header (Cabeçalho):
  - alg: Algoritmo de assinatura (HS256, RS256, ES256, none)
  - typ: Tipo do token (JWT)
  - kid: Key ID (para seleção de chave)
  - jku: JWK Set URL (chave pública)
  - cty: Content Type (para tokens aninhados)

Payload (Corpo):
  - iss (Issuer): Emissor do token
  - sub (Subject): Assunto do token (usuário)
  - aud (Audience): Audiência do token
  - exp (Expiration Time): Timestamp de expiração
  - nbf (Not Before): Não válido antes de
  - iat (Issued At): Emitido em
  - jti (JWT ID): Identificador único

Signature (Assinatura):
  - HMAC: assinatura simétrica (HS256, HS384, HS512)
  - RSA: assinatura assimétrica (RS256, RS384, RS512)
  - ECDSA: assinatura elíptica (ES256, ES384, ES512)
```

#### **Claims Registrados**

| Claim   | Nome            | Descrição                            | Obrigatório |
| ------- | --------------- | ------------------------------------ | ----------- |
| **iss** | Issuer          | Identifica o emissor do token        | Não         |
| **sub** | Subject         | Identifica o assunto (usuário)       | Não         |
| **aud** | Audience        | Identifica os destinatários          | Não         |
| **exp** | Expiration Time | Timestamp de expiração               | Recomendado |
| **nbf** | Not Before      | Timestamp antes do qual não é válido | Não         |
| **iat** | Issued At       | Timestamp de emissão                 | Recomendado |
| **jti** | JWT ID          | Identificador único do token         | Não         |

#### **Claims Personalizados**

```python
# Exemplo de claims personalizados
custom_claims = {
    "user_id": 12345,
    "username": "alice",
    "role": "admin",
    "permissions": ["read", "write", "delete"],
    "tenant_id": "tenant_001",
    "session_id": "sess_abc123",
    "device_info": {
        "browser": "Chrome",
        "os": "Windows",
        "ip": "192.168.1.100"
    }
}
```

***

### ⚙️ **Processo de Encoding**

#### **Fluxo de Criação do JWT**

```mermaid
sequenceDiagram
    participant S as Servidor
    participant E as Encoder
    participant V as Validador

    Note over S: 1. Criar header e payload
    S->>E: Header (JSON) + Payload (JSON)
    
    Note over E: 2. Codificar Base64URL
    E->>E: header_b64 = base64url(header)
    E->>E: payload_b64 = base64url(payload)
    
    Note over E: 3. Construir string de assinatura
    E->>E: signing_input = header_b64 + "." + payload_b64
    
    Note over E: 4. Assinar
    E->>E: signature = sign(signing_input, secret, algorithm)
    
    Note over E: 5. Codificar assinatura
    E->>E: signature_b64 = base64url(signature)
    
    Note over E: 6. Montar token final
    E->>V: token = header_b64 + "." + payload_b64 + "." + signature_b64
```

#### **Implementação do Encoding**

```python
#!/usr/bin/env python3
# jwt_encoding.py

import json
import base64
import hmac
import hashlib
import time

class JWTEncoder:
    """Implementação manual de encoding JWT"""
    
    def __init__(self, secret_key, algorithm='HS256'):
        self.secret_key = secret_key
        self.algorithm = algorithm
    
    def base64url_encode(self, data):
        """Codificar dados para Base64URL (RFC 4648)"""
        if isinstance(data, str):
            data = data.encode('utf-8')
        elif isinstance(data, dict):
            data = json.dumps(data).encode('utf-8')
        
        encoded = base64.b64encode(data)
        return encoded.decode('utf-8').rstrip('=').replace('+', '-').replace('/', '_')
    
    def create_header(self, algorithm=None, **kwargs):
        """Criar header JWT"""
        header = {
            "alg": algorithm or self.algorithm,
            "typ": "JWT"
        }
        header.update(kwargs)
        return header
    
    def create_payload(self, **claims):
        """Criar payload JWT com claims padrão"""
        payload = {
            "iat": int(time.time())
        }
        payload.update(claims)
        return payload
    
    def sign(self, signing_input):
        """Assinar a string de entrada"""
        if self.algorithm == 'HS256':
            signature = hmac.new(
                self.secret_key.encode('utf-8'),
                signing_input.encode('utf-8'),
                hashlib.sha256
            ).digest()
        elif self.algorithm == 'HS384':
            signature = hmac.new(
                self.secret_key.encode('utf-8'),
                signing_input.encode('utf-8'),
                hashlib.sha384
            ).digest()
        elif self.algorithm == 'HS512':
            signature = hmac.new(
                self.secret_key.encode('utf-8'),
                signing_input.encode('utf-8'),
                hashlib.sha512
            ).digest()
        else:
            raise ValueError(f"Algoritmo não suportado: {self.algorithm}")
        
        return signature
    
    def encode(self, payload_claims, header_claims=None):
        """Codificar JWT completo"""
        # 1. Criar header e payload
        header = self.create_header(**(header_claims or {}))
        payload = self.create_payload(**payload_claims)
        
        # 2. Codificar header e payload
        header_b64 = self.base64url_encode(header)
        payload_b64 = self.base64url_encode(payload)
        
        # 3. Construir string de assinatura
        signing_input = f"{header_b64}.{payload_b64}"
        
        # 4. Assinar
        signature = self.sign(signing_input)
        signature_b64 = self.base64url_encode(signature)
        
        # 5. Montar token final
        token = f"{header_b64}.{payload_b64}.{signature_b64}"
        
        return token

# Exemplo de uso
encoder = JWTEncoder("my_secret_key", "HS256")

token = encoder.encode(
    payload_claims={
        "sub": "1234567890",
        "name": "John Doe",
        "exp": int(time.time()) + 3600
    },
    header_claims={
        "kid": "key-1"
    }
)

print(f"Token gerado: {token}")
print(f"Tamanho: {len(token)} caracteres")
```

***

### 🔐 **Algoritmos de Assinatura**

#### **HMAC (Symmetric)**

```python
#!/usr/bin/env python3
# jwt_hmac.py

import jwt
import time

class HMACJWT:
    """Implementação de JWT com HMAC (simétrico)"""
    
    def __init__(self, secret_key):
        self.secret_key = secret_key
    
    def encode_hs256(self, payload):
        """HS256 - HMAC com SHA-256"""
        return jwt.encode(payload, self.secret_key, algorithm='HS256')
    
    def encode_hs384(self, payload):
        """HS384 - HMAC com SHA-384"""
        return jwt.encode(payload, self.secret_key, algorithm='HS384')
    
    def encode_hs512(self, payload):
        """HS512 - HMAC com SHA-512"""
        return jwt.encode(payload, self.secret_key, algorithm='HS512')
    
    def decode(self, token):
        """Decodificar e verificar token"""
        try:
            payload = jwt.decode(token, self.secret_key, algorithms=['HS256', 'HS384', 'HS512'])
            return payload
        except jwt.ExpiredSignatureError:
            return {"error": "Token expirado"}
        except jwt.InvalidTokenError as e:
            return {"error": f"Token inválido: {e}"}

# Exemplo
hmac_jwt = HMACJWT("my_super_secret_key_12345!")
payload = {
    "user_id": 123,
    "username": "alice",
    "exp": time.time() + 3600
}

token = hmac_jwt.encode_hs256(payload)
print(f"HS256 Token: {token[:50]}...")

decoded = hmac_jwt.decode(token)
print(f"Decodificado: {decoded}")
```

#### **RSA (Asymmetric)**

```python
#!/usr/bin/env python3
# jwt_rsa.py

import jwt
import time
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

class RSAJWT:
    """Implementação de JWT com RSA (assimétrico)"""
    
    def __init__(self):
        # Gerar par de chaves RSA
        self.private_key = self._generate_private_key()
        self.public_key = self.private_key.public_key()
    
    def _generate_private_key(self):
        """Gerar chave privada RSA"""
        return rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048
        )
    
    def get_private_key_pem(self):
        """Obter chave privada em formato PEM"""
        return self.private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        )
    
    def get_public_key_pem(self):
        """Obter chave pública em formato PEM"""
        return self.public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        )
    
    def encode_rs256(self, payload):
        """RS256 - RSA com SHA-256"""
        return jwt.encode(payload, self.get_private_key_pem(), algorithm='RS256')
    
    def encode_rs384(self, payload):
        """RS384 - RSA com SHA-384"""
        return jwt.encode(payload, self.get_private_key_pem(), algorithm='RS384')
    
    def encode_rs512(self, payload):
        """RS512 - RSA com SHA-512"""
        return jwt.encode(payload, self.get_private_key_pem(), algorithm='RS512')
    
    def decode(self, token):
        """Decodificar usando chave pública"""
        try:
            payload = jwt.decode(token, self.get_public_key_pem(), 
                                algorithms=['RS256', 'RS384', 'RS512'])
            return payload
        except jwt.ExpiredSignatureError:
            return {"error": "Token expirado"}
        except jwt.InvalidTokenError as e:
            return {"error": f"Token inválido: {e}"}

# Exemplo
rsa_jwt = RSAJWT()
payload = {
    "user_id": 123,
    "username": "alice",
    "role": "admin",
    "exp": time.time() + 3600
}

token = rsa_jwt.encode_rs256(payload)
print(f"RS256 Token: {token[:50]}...")

decoded = rsa_jwt.decode(token)
print(f"Decodificado: {decoded}")
```

#### **ECDSA (Elliptic Curve)**

```python
#!/usr/bin/env python3
# jwt_ecdsa.py

import jwt
import time
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec

class ECDSAJWT:
    """Implementação de JWT com ECDSA (curva elíptica)"""
    
    def __init__(self):
        # Gerar par de chaves EC
        self.private_key = self._generate_private_key()
        self.public_key = self.private_key.public_key()
    
    def _generate_private_key(self):
        """Gerar chave privada EC (P-256)"""
        return ec.generate_private_key(ec.SECP256R1())
    
    def get_private_key_pem(self):
        """Obter chave privada em formato PEM"""
        return self.private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        )
    
    def get_public_key_pem(self):
        """Obter chave pública em formato PEM"""
        return self.public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        )
    
    def encode_es256(self, payload):
        """ES256 - ECDSA com P-256 e SHA-256"""
        return jwt.encode(payload, self.get_private_key_pem(), algorithm='ES256')
    
    def encode_es384(self, payload):
        """ES384 - ECDSA com P-384 e SHA-384"""
        return jwt.encode(payload, self.get_private_key_pem(), algorithm='ES384')
    
    def encode_es512(self, payload):
        """ES512 - ECDSA com P-521 e SHA-512"""
        return jwt.encode(payload, self.get_private_key_pem(), algorithm='ES512')
    
    def decode(self, token):
        """Decodificar usando chave pública"""
        try:
            payload = jwt.decode(token, self.get_public_key_pem(),
                                algorithms=['ES256', 'ES384', 'ES512'])
            return payload
        except jwt.ExpiredSignatureError:
            return {"error": "Token expirado"}
        except jwt.InvalidTokenError as e:
            return {"error": f"Token inválido: {e}"}

# Exemplo
ecdsa_jwt = ECDSAJWT()
payload = {
    "user_id": 123,
    "username": "alice",
    "exp": time.time() + 3600
}

token = ecdsa_jwt.encode_es256(payload)
print(f"ES256 Token: {token[:50]}...")

decoded = ecdsa_jwt.decode(token)
print(f"Decodificado: {decoded}")
```

***

### 💻 **Implementação em Linguagens**

#### **Python (PyJWT)**

```python
#!/usr/bin/env python3
# jwt_python.py

import jwt
import time
from datetime import datetime, timedelta

class PythonJWT:
    """Implementação JWT com PyJWT"""
    
    def __init__(self, secret_key):
        self.secret_key = secret_key
    
    def create_token(self, user_id, username, role, expires_in=3600):
        """Criar token JWT"""
        payload = {
            'user_id': user_id,
            'username': username,
            'role': role,
            'iat': datetime.utcnow(),
            'exp': datetime.utcnow() + timedelta(seconds=expires_in),
            'jti': self.generate_jti()
        }
        
        token = jwt.encode(payload, self.secret_key, algorithm='HS256')
        return token
    
    def verify_token(self, token):
        """Verificar token JWT"""
        try:
            payload = jwt.decode(token, self.secret_key, algorithms=['HS256'])
            return {'valid': True, 'payload': payload}
        except jwt.ExpiredSignatureError:
            return {'valid': False, 'error': 'Token expirado'}
        except jwt.InvalidTokenError as e:
            return {'valid': False, 'error': str(e)}
    
    def generate_jti(self):
        """Gerar JWT ID único"""
        import uuid
        return str(uuid.uuid4())

# Exemplo
jwt_py = PythonJWT("my_secret_key")
token = jwt_py.create_token(123, "alice", "admin")
print(f"Token: {token}")

verification = jwt_py.verify_token(token)
print(f"Verificação: {verification}")
```

#### **Node.js (jsonwebtoken)**

```javascript
// jwt_node.js
const jwt = require('jsonwebtoken');

class NodeJWT {
    constructor(secretKey) {
        this.secretKey = secretKey;
    }
    
    createToken(userId, username, role, expiresIn = '1h') {
        const payload = {
            user_id: userId,
            username: username,
            role: role,
            jti: this.generateJTI()
        };
        
        const token = jwt.sign(payload, this.secretKey, {
            algorithm: 'HS256',
            expiresIn: expiresIn,
            issuer: 'myapp.com',
            audience: 'myapp-users'
        });
        
        return token;
    }
    
    verifyToken(token) {
        try {
            const decoded = jwt.verify(token, this.secretKey, {
                algorithms: ['HS256'],
                issuer: 'myapp.com',
                audience: 'myapp-users'
            });
            return { valid: true, payload: decoded };
        } catch (error) {
            return { valid: false, error: error.message };
        }
    }
    
    generateJTI() {
        return require('crypto').randomBytes(16).toString('hex');
    }
}

// Exemplo
const jwtNode = new NodeJWT('my_secret_key');
const token = jwtNode.createToken(123, 'alice', 'admin');
console.log(`Token: ${token}`);

const verification = jwtNode.verifyToken(token);
console.log(`Verificação:`, verification);
```

#### **Java (JJWT)**

```java
// JWTJava.java
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;
import java.util.UUID;

public class JWTJava {
    private Key secretKey;
    
    public JWTJava() {
        this.secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    }
    
    public String createToken(int userId, String username, String role) {
        Date now = new Date();
        Date expiry = new Date(now.getTime() + 3600000); // 1 hora
        
        String token = Jwts.builder()
            .setSubject(String.valueOf(userId))
            .claim("username", username)
            .claim("role", role)
            .setId(UUID.randomUUID().toString())
            .setIssuedAt(now)
            .setExpiration(expiry)
            .setIssuer("myapp.com")
            .setAudience("myapp-users")
            .signWith(secretKey, SignatureAlgorithm.HS256)
            .compact();
        
        return token;
    }
    
    public boolean verifyToken(String token) {
        try {
            Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
```

#### **Go (golang-jwt)**

```go
// jwt_go.go
package main

import (
    "time"
    "github.com/golang-jwt/jwt/v5"
)

type GoJWT struct {
    secretKey []byte
}

func NewGoJWT(secretKey string) *GoJWT {
    return &GoJWT{
        secretKey: []byte(secretKey),
    }
}

func (j *GoJWT) CreateToken(userID int, username, role string) (string, error) {
    claims := jwt.MapClaims{
        "user_id":   userID,
        "username":  username,
        "role":      role,
        "jti":       generateJTI(),
        "iat":       time.Now().Unix(),
        "exp":       time.Now().Add(time.Hour).Unix(),
        "iss":       "myapp.com",
        "aud":       "myapp-users",
    }
    
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(j.secretKey)
}

func (j *GoJWT) VerifyToken(tokenString string) (jwt.MapClaims, error) {
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        return j.secretKey, nil
    })
    
    if err != nil {
        return nil, err
    }
    
    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        return claims, nil
    }
    
    return nil, jwt.ErrSignatureInvalid
}
```

***

### 🔍 **Validação e Decoding**

#### **Validação de JWT**

```python
#!/usr/bin/env python3
# jwt_validation.py

import jwt
import time
from datetime import datetime

class JWTValidator:
    """Validador completo de JWT"""
    
    def __init__(self, secret_key, issuer=None, audience=None):
        self.secret_key = secret_key
        self.issuer = issuer
        self.audience = audience
    
    def validate_token(self, token):
        """Validar token JWT com todas as verificações"""
        try:
            # Opções de validação
            options = {
                'verify_signature': True,
                'verify_exp': True,
                'verify_nbf': True,
                'verify_iat': True,
                'verify_aud': True if self.audience else False,
                'verify_iss': True if self.issuer else False
            }
            
            payload = jwt.decode(
                token,
                self.secret_key,
                algorithms=['HS256'],
                options=options,
                issuer=self.issuer,
                audience=self.audience
            )
            
            return {
                'valid': True,
                'payload': payload,
                'error': None
            }
            
        except jwt.ExpiredSignatureError:
            return {
                'valid': False,
                'payload': None,
                'error': 'Token expirado'
            }
        except jwt.InvalidIssuerError:
            return {
                'valid': False,
                'payload': None,
                'error': 'Issuer inválido'
            }
        except jwt.InvalidAudienceError:
            return {
                'valid': False,
                'payload': None,
                'error': 'Audience inválida'
            }
        except jwt.InvalidTokenError as e:
            return {
                'valid': False,
                'payload': None,
                'error': f'Token inválido: {str(e)}'
            }
    
    def get_payload_without_validation(self, token):
        """Obter payload sem validar assinatura (apenas decode)"""
        try:
            import base64
            import json
            
            parts = token.split('.')
            if len(parts) != 3:
                return None
            
            payload_b64 = parts[1]
            # Adicionar padding se necessário
            payload_b64 += '=' * (4 - len(payload_b64) % 4)
            payload_json = base64.urlsafe_b64decode(payload_b64)
            return json.loads(payload_json)
            
        except Exception:
            return None
    
    def check_expiration(self, token):
        """Verificar se token está expirado sem validar assinatura"""
        payload = self.get_payload_without_validation(token)
        if payload and 'exp' in payload:
            exp = payload['exp']
            now = time.time()
            if exp < now:
                return {'expired': True, 'expired_at': exp, 'now': now}
            return {'expired': False, 'expires_at': exp, 'remaining': exp - now}
        return {'expired': None, 'message': 'Sem claim exp'}

# Exemplo
validator = JWTValidator("my_secret_key", issuer="myapp.com", audience="myapp-users")

token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

result = validator.validate_token(token)
print(f"Validação: {result}")
```

#### **Middleware de Validação (Flask)**

```python
#!/usr/bin/env python3
# jwt_middleware.py

from functools import wraps
import jwt
from flask import request, jsonify, current_app

def token_required(f):
    """Decorator para proteger rotas com JWT"""
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        
        # Verificar header Authorization
        if 'Authorization' in request.headers:
            auth_header = request.headers['Authorization']
            if auth_header.startswith('Bearer '):
                token = auth_header.split(' ')[1]
        
        if not token:
            return jsonify({'message': 'Token não fornecido'}), 401
        
        try:
            # Decodificar token
            payload = jwt.decode(
                token,
                current_app.config['SECRET_KEY'],
                algorithms=['HS256']
            )
            current_user = payload
        except jwt.ExpiredSignatureError:
            return jsonify({'message': 'Token expirado'}), 401
        except jwt.InvalidTokenError:
            return jsonify({'message': 'Token inválido'}), 401
        
        return f(current_user, *args, **kwargs)
    
    return decorated

# Uso no Flask
# @app.route('/protected')
# @token_required
# def protected_route(current_user):
#     return jsonify({'message': f'Bem-vindo {current_user["username"]}'})
```

***

### 🛡️ **Segurança e Boas Práticas**

#### **Configuração Segura**

```python
#!/usr/bin/env python3
# secure_jwt.py

import jwt
import secrets
import time
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

class SecureJWT:
    """Implementação segura de JWT"""
    
    def __init__(self):
        # Usar RSA-2048 ou superior
        self.private_key = self._generate_rsa_key()
        self.public_key = self.private_key.public_key()
        self.issuer = "api.example.com"
        self.audience = "example.com"
    
    def _generate_rsa_key(self):
        """Gerar chave RSA-2048"""
        return rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048
        )
    
    def create_token(self, user_id, roles, session_id):
        """Criar token seguro com validações"""
        now = int(time.time())
        
        payload = {
            # Claims padrão
            'iss': self.issuer,
            'sub': str(user_id),
            'aud': self.audience,
            'exp': now + 900,      # 15 minutos
            'nbf': now,
            'iat': now,
            'jti': secrets.token_hex(16),  # ID único
            
            # Claims personalizadas
            'user_id': user_id,
            'roles': roles,
            'session_id': session_id
        }
        
        # Usar RS256 (assimétrico)
        token = jwt.encode(
            payload,
            self._get_private_key_pem(),
            algorithm='RS256'
        )
        
        return token
    
    def verify_token(self, token):
        """Verificar token com todas as validações"""
        try:
            payload = jwt.decode(
                token,
                self._get_public_key_pem(),
                algorithms=['RS256'],
                issuer=self.issuer,
                audience=self.audience,
                options={
                    'require_exp': True,
                    'require_iat': True,
                    'require_nbf': True
                }
            )
            return payload
        except jwt.ExpiredSignatureError:
            return None
        except jwt.InvalidTokenError:
            return None
    
    def _get_private_key_pem(self):
        """Obter chave privada em PEM"""
        return self.private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        )
    
    def _get_public_key_pem(self):
        """Obter chave pública em PEM"""
        return self.public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        )

# Exemplo
secure = SecureJWT()
token = secure.create_token(12345, ['user', 'admin'], 'session_abc')
print(f"Token seguro: {token[:50]}...")

verified = secure.verify_token(token)
print(f"Verificado: {verified}")
```

#### **Boas Práticas de Segurança**

```yaml
Recomendações de Segurança:
  
  Algoritmos:
    ✓ Usar RS256 ou ES256 (assimétricos)
    ✓ Nunca usar algoritmo 'none'
    ✓ Evitar HS256 em produção (chave compartilhada)
  
  Claims:
    ✓ Sempre incluir 'exp' (expiração)
    ✓ Usar 'nbf' e 'iat' para proteção
    ✓ Validar 'iss' e 'aud'
    ✓ Usar 'jti' único para revogação
  
  Chaves:
    ✓ Chaves de pelo menos 2048 bits (RSA)
    ✓ Rotacionar chaves periodicamente
    ✓ Armazenar chaves de forma segura (HSM)
    ✓ Implementar key rotation
  
  Armazenamento:
    ✓ Não armazenar tokens em localStorage
    ✓ Usar httpOnly cookies com Secure e SameSite
    ✓ Implementar blacklist para revogação
    ✓ Usar refresh tokens com rotação
  
  Validação:
    ✓ Validar assinatura sempre
    ✓ Verificar expiração em cada request
    ✓ Validar claims de negócio
    ✓ Rate limiting por token
```

***

### 🛠️ **Ferramentas e Debug**

#### **Ferramentas de Debug**

```bash
# jwt.io - Decodificador online
curl https://jwt.io/#debugger

# jwt-cli - CLI para JWT
npm install -g jwt-cli
jwt decode <token>
jwt verify <token> --secret <secret>

# PyJWT CLI
python -m jwt.encode --payload '{"user": "alice"}' --secret mysecret
python -m jwt.decode --token <token> --secret mysecret

# JWT Tool
pip install jwt_tool
jwt_tool <token>
jwt_tool -t <token> -X a  # Testar algoritmo none
```

#### **Script de Debug**

```python
#!/usr/bin/env python3
# jwt_debug.py

import jwt
import json
import base64
import sys

class JWTDebug:
    """Ferramenta de debug para JWT"""
    
    @staticmethod
    def inspect_token(token):
        """Inspecionar token JWT"""
        parts = token.split('.')
        
        print("=== JWT Debug Information ===")
        print(f"Token: {token[:50]}...")
        print(f"Parts: {len(parts)}")
        
        for i, part in enumerate(parts):
            part_name = ['Header', 'Payload', 'Signature'][i] if i < 3 else f'Part {i}'
            print(f"\n[{part_name}]")
            
            try:
                # Adicionar padding
                padded = part + '=' * (4 - len(part) % 4)
                decoded = base64.urlsafe_b64decode(padded)
                
                try:
                    json_data = json.loads(decoded)
                    print(json.dumps(json_data, indent=2))
                except:
                    print(f"Raw (hex): {decoded.hex()}")
                    print(f"Raw (text): {decoded}")
                    
            except Exception as e:
                print(f"Error decoding: {e}")
    
    @staticmethod
    def test_algorithm(token, secret, algorithm='HS256'):
        """Testar algoritmo específico"""
        try:
            decoded = jwt.decode(token, secret, algorithms=[algorithm])
            print(f"✅ Algoritmo {algorithm} funciona")
            return decoded
        except Exception as e:
            print(f"❌ Algoritmo {algorithm} falhou: {e}")
            return None
    
    @staticmethod
    def brute_force_secret(token, wordlist):
        """Força bruta de segredo (apenas para testes)"""
        import os
        if not os.path.exists(wordlist):
            print(f"Wordlist não encontrada: {wordlist}")
            return None
        
        with open(wordlist, 'r') as f:
            for line in f:
                secret = line.strip()
                try:
                    decoded = jwt.decode(token, secret, algorithms=['HS256'])
                    print(f"✅ Secret encontrada: {secret}")
                    return secret
                except:
                    continue
        
        print("❌ Secret não encontrada")
        return None

# Exemplo
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Uso: jwt_debug.py <token>")
        sys.exit(1)
    
    JWTDebug.inspect_token(sys.argv[1])
```

***

### 📊 **Conclusão e Boas Práticas**

#### **Resumo Técnico**

```yaml
JWT Encoding:
  ✅ Formato compacto e autossuficiente
  ✅ Suporta múltiplos algoritmos de assinatura
  ✅ Ideal para autenticação stateless
  ✅ Amplamente suportado

Desafios de Segurança:
  ❌ Algoritmo none - bypass completo
  ❌ Chave fraca - brute force
  ❌ Falta de validação - vulnerabilidades
  ❌ Revogação complexa

Boas Práticas:
  - Usar algoritmos fortes (RS256, ES256)
  - Validar todas as claims
  - Implementar blacklist para revogação
  - Rotacionar chaves periodicamente
```

#### **Referências**

* **RFC 7519** - JSON Web Token (JWT)
* **RFC 7515** - JSON Web Signature (JWS)
* **RFC 7516** - JSON Web Encryption (JWE)
* **RFC 7517** - JSON Web Key (JWK)
* **RFC 7518** - JSON Web Algorithms (JWA)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/criptografia/encodagem-encoding/jwt.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
