Userinfo endpoint 403

I’m currently attempting to implement an OAuth flow to my platform so users can login with their BattleNet accounts. Unfortunately, after retrieving their access token, grabbing their user data from /oauth/userinfo returns me a 403 forbidden response from the apache server.

That’s one example URL that I’m sending a get request to:

https://eu.battle.net/oauth/userinfo?:region=eu&access_token=<ACCESS_TOKEN>

Posting the token to /oauth/check_token yields the following reply, so I feel somewhat confident, that the token itself is valid, which leaves me at a loss of what the actual problem is:

{
  "scope": [
    "openid"
  ],
  "exp": <EXPIRY_DATE>,
  "authorities": [
    {
      "authority": "ROLE_CLIENT"
    }
  ],
  "client_id": <CLIENT_ID>
}

I’ve attempted to retrieve the info through access_token query param and through authorization header (separately), but the server returns 403 regardless of the chosen method. Varying the :region query parameter or the endpoint used also does not change the result.

Heya KitCat,

I think there is an issue with your userinfo URL.

Refer to the documentation for the code authorization flow develop[dot]battle[dot]net/documentation/guides/using-oauth/authorization-code-flow under the “Getting a User’s Account ID and BattleTag” header and you will see an example call being made to the userinfo endpoint.

The :region param referenced on the API reference is for the URL subdomain, not as a query param.

curl -X GET
'https://{region}.battle.net/oauth/userinfo'
-H 'Authorization: Bearer <access token>
1 Like

Thanks for helping out. I wasn’t completely sure on whether it was necessary, and included it on a “just in case” basis, but the result is the same even without the :region query parameter, unfortunately.

Just to confirm, are you sure you are passing the user contextual OAuth token in the call to /userinfo?

Also, which language are you working in? Are you able to test your tokens using the CURL command above?

1 Like

Just to confirm, are you sure you are passing the user contextual OAuth token in the call to /userinfo ?

I’ve tried passing it either as header or as query parameter, but either one results in a 403. The token has been obtained through the OAuth process (redirecting user to oauth/authorize, obtaining the returned code, posting that server-side to oauth/token to obtain the final token). The entire OAuth part is handled by a library, which works fine for about 25+ other providers I’ve integrated so far, so I do believe there’s no fault in there for the moment.

Also, which language are you working in? Are you able to test your tokens using the CURL command above?

My project language is php, and the call is through Guzzle but I’m using the Insomnia REST tool to debug the API call. Either one (and for a sanity check also a plain CURL call) all yield a 403 as result.

Sending the token to oauth/check_token returns the result visible in the first post, so I at least believe that the token is correct, and has the required scope.

I just tested a simple POST request to us.battle.net/oauth/userinfo?access_token={token} without any body and it returns something like this:

{
  "sub": "00000000",
  "id": 00000000,
  "battletag": "Battletag#000"
}

If you are receiving a 403 you are either passing an incorrect query string for the token, or there is something wrong with the token.
Did you assign any OAuth2 scopes (wow.profile, sc2.profile) when generating the token ? I’m not sure this would affect the results but it is worth a try.

Edit: Can you try going over the official docs OAuth2 profile endpoint and using the same token by clicking on provide your own access token ?
If the token is fine you should be able to retrieve a list of characters.

1 Like

Thanks for the input. I’ve used the /wow/user/characters endpoint in the API to generate another token. Running that against oauth/check_token yields me a different result than before, so there indeed seems to be something off with my token fetch.

{
“exp”: <EXPIRY_DATE>,
“user_name”: <USER_NAME>,
“authorities”: [
“IS_AUTHENTICATED_FULLY”,
“ROLE_USER”
],
“client_id”: <CLIENT_ID>,
“scope”: [
“wow.profile”,
“sc2.profile”
]
}

Note how the authorities have changed. It seems a little bit strange to me that my OAuth process does return me a token that appears to be valid, even though it does not grant any authority, more like an empty token without an actual user.

I’ve checked account[dot]blizzard[dot]com/connections#authorized-applications, which lists that my app has full access to Account ID, BattleTag and my Account Identity (plus my WoW Profile), as a sanity check that I didn’t accidentally blocked it, but all is good on that front.

I’m currently investigating my token fetch procedure to see if I can find the point of failure, and why it still returns me what appears to be a working - albeit empty blank? - token.

Check if the grant type on on the token exchange is authorization_code, if it is client_credentials it will grant you a token not related to your account, but you still can use that token to more generic endpoints that doesn’t involve profile data.

Also in case you missed there is an unoficial discord where there is always someone willing to help.

1 Like

I just noticed the wrong grant type as well, which fixed the issue. Thanks for helping to track this down! Got a working access token now.