The vulnerability came from the outlook-integration.harvestapp.com. It used a JSON object as `state` containing instructions once the OAuth2 Callback succeeded.
The property `subdomain` was used to redirect the browser to a subdomain of harvestapp.com, passing the `#id-token`. The problem came from the fact that the value of `subdomain` was injected directly to:
* the additional redirect using the JSON object in state
* the `subdomain` not being properly verified
* the implicit grant being supported
Which allowed an attacker to get an access token for a user's Microsoft account.
From my reading, this seems to be entirely an issue due to an improper implementation on Harvest's side, nothing to do with Microsoft's implementation of OAuth. Am I correct?
It seems pretty clear to me from reading the blog post that the issue was what I outlined (sorry for the lack of list formatting, I always forget I need an extra line after each bullet point).
All they had to do was sanitize the subdomain var to only allow values valid in host part of a URL. But also, one of the state parameter's primary uses is exactly to prevent XSRF attacks like this by using a random nonce value so that you can validate from the redirect that your system was the initiator of the auth request. The data in this state was not sensitive, so encryption is not really necessary.
The property `subdomain` was used to redirect the browser to a subdomain of harvestapp.com, passing the `#id-token`. The problem came from the fact that the value of `subdomain` was injected directly to:
https://${subdomain}.harvestapp.com/...#id-token=...
By setting the `subdomain` in JSON payload to `attacker-controlled.com/` (note the trailing slash), the URL become:
..thus redirects the browser to another domain, leaking the token.