Microsoft Advertising API returns access token with fewer scopes than initially granted after using refresh token to obtain a new access token.
It turned around, that it happens because "golang.org/x/oauth2" does not send scope parameter on refresh request.
It seems, that without this parameter Microsoft API returns access token with default minimal set of scopes - not one was provided initially.
When request is made with this parameter, it forces Microsoft API to return access token with correct scope.
golang#322 https://go-review.googlesource.com/c/oauth2/+/135935
golang#448 https://go-review.googlesource.com/c/oauth2/+/264037
golang#509 https://go-review.googlesource.com/c/oauth2/+/332749
golang#540 https://go-review.googlesource.com/c/oauth2/+/381916
golang#559 https://go-review.googlesource.com/c/oauth2/+/394696
golang#579 https://go-review.googlesource.com/c/oauth2/+/421174
At this point it's obvious that changes have slim chances to make into upstream, because of maintainers' position, best stated here:
We are not willing to implement workarounds for each broken OAuth 2.0 implementation. If this is a blocker for you, please maintain your own of the oauth2 package with the necessary patches.
It equally unlikely to persuade Microsoft to make the change. So, here we are.
According to RFC, it seems, that issue is indeed on Microsoft side. But looking at history it is clear that it persisted for quite a long already. Many PRs have been submitted (and rejected or ignored) to the upstream project during this time. It seems, that both sides are stubborn to change their mind.
Obviously, we (application programmers) are not in position of endlessly arguing with Microsoft and Google about correct RFC implementation. We need some practical workaround to make our work at hands. But just in case, I'll provide couple of arguments in support of this change.
First of all, RFC 6749 sections 3.3 and 6 says, that indeed this parameter is optional. But "optional" for me sounds like we should have an option to provide it, if we have to. So, implementation should not prohibit us to do it.
Second, taking aside Microsoft issue, RFC allows to either send the same or fewer scopes. May be it is a rare use case, but it is in RFC and upstream implementation does not address it.
In the Go code continue to import lib as usual:
import "golang.org/x/oauth2/google"
But in the go.mod
put line like following (to replace ustream lib with forked one):
replace golang.org/x/oauth2 v0.x.x => github.com/nikolay-turpitko/oauth2 v0.0.0-xxxx-xxxx
Where version of upstream and fork libs should be replaced with current ones. To obtain current version for above line execute the followning CLI command:
go list -m github.com/nikolay-turpitko/oauth2@latest