What's the purpose of the code you're entering from the app? Isn't that a bit superfluous/couldn't the app open a communications channel with the server via the QR code you scan and provide that itself?
Then the app relies purely on the ssl cert of the server, for mitm mitigation. This way, the qr can contain a signed reply to the code, which adds a layer.
Wait, I don't get it. I understand that the server is signing a challenge with a key presumably known to the client. But why can't the app submit the challenge programmatically upon scanning a QR code? It would still verify the signature!