What is the correct way to implement USB hardware?
Correct way to implement USB hardware is to follow ALL manufacturer's recommendations. If a hardware developer has no experience with USB implementations, the best way is to look at schematics and layout on development boards/kits.

In this particular case the implementation has several deficiencies. First it should be noted that this is a full-speed-only device, and transmission line effects (and thus the source termination) plays minor role. However, to "play nice", the manufacturer uses 22R series resistors, apparently to compensate electrical driver deficiency common to cheap FS PHY implementation IP. This schematics is from Olimex development board:

All application schematics I've seen for STM32Fxx uses 22R.

One thing is clear that 22R pull up on D+ in the second schematics is ABSOLUTELY inappropriate.

Second, if this is a device-only design, there must be two things done:


VBUS from Type-B connector must go to some I/O pin like "OTG_FS_VBUS" for system to be able to sense the presence of VBUS on attached cable, and
VBUS capacitor should be more than 1 uF but less than 10 uF.


Another detail is that ESD protection circuit should be biased from 3.3V, not +5V. 

However, these are minor details that are not critical for the device operation and interface stability. 

Given the vague description of "frequent disconnect" problems with "certain hosts" but not with others, I would hazard to guess that the problem is in USB interface clock going out of range. Different USB hosts may have different tolerance to USB frequency deviation, and this is the most common overlooked cause of interface instability.

To make it certain, you should run the eye diagram test on your USB port off the STM32F board. There are documents on how to perform this test, depending of the equipment you have. Google for {usb eye diagram measurement}.

USB specifications call for maximum deviation from the 12Mbps data rate by +-2000 ppm. Some hosts can tolerate +-5000 ppm, some 2200ppm. It is most likely that the system crystal oscillator is not tuned properly, and the interface clock is quite off. Typical behavior is that everything might be fine on enumeration process where USB packets are short, but longer data packets will lose synch and data corruption will follow. 

In general, when some interface behaves flaky, first thing is to make sure that signal amplitudes and frequencies are well within interface specification. "Random engineering" such as replacement of resistors or pushing crazy pull-ups usually is of no help.