jwtExtractor static method
Middleware que extrae y valida JWT desde Authorization header
jwtSecret - Clave secreta para validar la firma JWT
excludePaths - Paths que no requieren extracción JWT
Extrae el JWT del header "Authorization: Bearer
Implementation
static Middleware jwtExtractor({
required String jwtSecret,
List<String> excludePaths = const [],
}) {
return (Handler innerHandler) {
return (Request request) async {
final path = request.requestedUri.path;
final requestId = request.context['request_id'] as String? ?? 'unknown';
// Saltar extracción para paths excluidos
if (excludePaths.any((excludePath) => path.startsWith(excludePath))) {
Log.d('[$requestId] JWT extraction skipped for excluded path: $path');
return await innerHandler(request);
}
try {
Log.d('[$requestId] Extracting JWT from Authorization header');
// Obtener Authorization header
final authHeader = request.headers['authorization'];
if (authHeader == null || !authHeader.startsWith('Bearer ')) {
Log.d('[$requestId] No Bearer token found in Authorization header');
// Agregar contexto vacío para endpoints que no requieren JWT
final updatedRequest = request.change(
context: {...request.context, 'jwt_payload': null}
);
return await innerHandler(updatedRequest);
}
// Extraer token
final token = authHeader.substring(7);
if (token.isEmpty) {
Log.w('[$requestId] Empty JWT token provided');
return _unauthorizedResponse('Invalid JWT token format', requestId);
}
// Validar y decodificar JWT
final jwtPayload = await _validateAndDecodeJWT(token, jwtSecret);
if (jwtPayload == null) {
Log.w('[$requestId] JWT validation failed');
return _unauthorizedResponse('Invalid or expired JWT token', requestId);
}
Log.i('[$requestId] JWT validated successfully for user: ${jwtPayload['user_id'] ?? 'unknown'}');
// Agregar payload JWT al contexto del request
final updatedRequest = request.change(
context: {
...request.context,
'jwt_payload': jwtPayload,
'user_id': jwtPayload['user_id'],
'user_email': jwtPayload['email'],
'user_role': jwtPayload['role'],
}
);
return await innerHandler(updatedRequest);
} catch (e, stackTrace) {
Log.e('[$requestId] JWT extraction error: $e');
return Response(
500,
body: jsonEncode({
'success': false,
'error': {
'code': 'INTERNAL_ERROR',
'message': 'Authentication system error',
'status_code': 500,
},
'timestamp': DateTime.now().toIso8601String(),
'request_id': requestId,
}),
headers: {
'Content-Type': 'application/json',
'X-Request-ID': requestId,
},
);
}
};
};
}