通过 golang 获取 Microsoft oauth2 令牌的随机错误。org/x/oauth2

Random errors acquiring Microsoft oauth2 token via golang.org/x/oauth2

我使用标准 go 库 golang.org/x/oauth2 从 Microsoft 用户那里获取 OAuth2 令牌。

这是我使用的 oauth2 配置:

return oauth2.Config{
    ClientID:     clientID,
    ClientSecret: clientSecret,
    Endpoint:     microsoft.AzureADEndpoint("common"),
    Scopes: []string{
        "https://graph.microsoft.com/.default",
    },
}

这就是我获得重定向的方式 URL:

oauth2Config.AuthCodeURL(state, oauth2.ApprovalForce, oauth2.AccessTypeOffline)

这就是我将 oauth2 回调中获取的代码交换到 oauth2 令牌的方式:

oauth2Config.Exchange(ctx, code)

我使用相同的代码与 github、google 云平台、bitbucket 和 digitalocean 集成。它对我来说一直运行良好,它确实适用于 Microsoft,但有时我 随机 遇到以下错误之一:

AADSTS90013 Invalid input received from the user

AADSTS900144: The request body must contain the following parameter: 'grant_type'.

而且我不明白可能是什么原因。第一个错误可能是由 Microsoft 同意屏幕中的一些 JS 错误引起的。第二个错误毫无意义——oauth2 库正确设置了 grant_type 值,我搜索了这个错误,它说问题可能出在不正确的编码上,应该是 x-www-form-urlencoded 但我已经查找了 oauth2 库并确认这正是它的作用。

或者同一用户下重复获取token超时

UPD:我在将代码交换为令牌时遇到这些错误

UPD2:我开始随机收到其他供应商的 oauth2 错误,例如 DigitalOcean,这些错误也发生在代码到令牌交换的过程中。类似这样的错误:

ERROR STACKTRACE: oauth2: cannot fetch token: 400 Bad Request Response: {"error":"bad_request","error_description":"invalid semicolon separator in query"}{"error":"invalid_request","error_description":"The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."} could not get auth token

我在我的 oauth2 配置中查找了值,一切都是正确的,但是这些值没有 url 编码(我假设 oauth2 库处理这个)。

我最近将 go 升级到了 1.17.6

UPD3:我注意到我的 DigitalOcean 和 Microsoft 的 oauth2 配置都没有指定 AuthStyle,所以我手动将其设置为 oauth2.AuthStyleInParams。但这仍然没有解决问题。在对 DigitalOcean 进行几次反复尝试后,它开始随机出现 return 以下错误:

Response: {"error":"bad_request","error_description":"invalid semicolon separator in query"}{"error":"invalid_request","error_description":"The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."}

我什至认为这不是有效错误,请求 URL 和 body

中都没有分号

UPD4。这听起来可能很愚蠢,但是当我重新启动我的应用程序时(我 run-debug 它通过 GoLand)DigitalOcean oauth 工作正常,直到我通过 oauth2 连接 Microsoft 帐户(也可以正常工作),但是如果我连接(重新连接)DigitalOcean重新登录然后它就停止工作了¯_(ツ)_/¯

UPD5。下面是 oauth2 库中 doTokenRoundTrip 函数的调试观察。令牌交换请求 returns 400 错误请求

请求body:

client_id=[redacter]&client_secret=[redacted]&code=e50e6dc91ec6b855becdef7a32cc4e28684851ccf385b2f6bb667ed6ec1172df&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fv1%2Fdigitalocean%2Foauth2%2Fcallback

URL 和 body 我觉得都不错。但是,此 return 出现以下错误:

Response: {"error":"bad_request","error_description":"invalid URL escape "%\x9b\x06""}{"error":"invalid_request","error_description":"The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."}

UPD6。交换请求 headers:

我认为第二个错误是指配置中缺少 grant_type

grant_type:authorization_code, 
code: {code you got from the authorization step}, 
client_secret: ****

其他获取OAuth 2.0 Token的方式,请参考此Document

由额外的 header 引起的问题。通常它应该只是 Content-Type: application/x-www-form-urlencoded header,但正如您在上面看到的那样,还有额外的 header,包括 Content-Encoding: gzip,这可能会导致问题。这些 headers 在我通过 oauth2 连接 Microsoft 帐户后添加,更具体地说是因为我在获取令牌后使用了 microsoft graph sdk (github.com/microsoftgraph/msgraph-sdk-go)。此 SDK 实现 RoundTripper 接口,最终添加额外的 headers.

已将问题提交至 graph sdk https://github.com/microsoftgraph/msgraph-sdk-go/issues/91