Fetch all characters error, status of migration?

The /wow/user/characters endpoint returns a 403 error even after I successfully logged into my app with passport bnet in a node is application. I get the response, the id, BattleTag and access token but I cannot then use that access token to getmy characters. Trying with the token validateI get a response that I am fully authorized but scope seems to be missing. Am I just in the middle of the migration orwhy doesnot the character fetch api work?

Which scopes are you requesting when you request the access token through the Authorization Code Flow? The characters request requires that you request the wow.profile scope when performing the Authorization Code Flow. Are you requesting this scope?

1 Like

Hi!

Yes using passport bnet it looks like this:
passport.use(

    new BnetStrategy(

      { clientID: process.env.BNET_ID,

        clientSecret: process.env.BNET_SECRET,

        scope: "wow.profile",

        callbackURL: "mypage/wowclassic/auth/bnet/callback",

        region: "eu"

      }, function(accessToken, refreshToken, profile, done) {

        process.nextTick(function () {

          return done(null, profile);

        });

      })

  );

However, after receiving this token, i can make a validation request and get a result that says “scope: []”

No idea why

Is this snippet the exact code you are running or did you leave some parts out?
I ask because you aren’t saving off the accessToken value returned in the callback. When you complete the Authorization Code Flow, you are given back an access token which ‘belongs’ to the user which logged into your site. This ‘user specific’ access token is the one you need to use when calling /user/characters, not the token you retrieved from the Client Credentials flow (if that’s what you are doing).

You have to save this token in the user session somewhere. Usually, you would invoke the done() callback with a composed object that includes both the token and profile done({ accessToken, ...profile });

You can then reference req.user.accessToken in your app.get((req, res, next) => {...}) methods when you call the /user/characters endpoint.

I assume the confusion here is coming from the example app (github[dot]com/Blizzard/passport-bnet/blob/master/examples/express/app.js#L46), which doesn’t really cover using the accessToken returned from the Authorization Code Flow after completing the flow.

Woops! I actually just did some testing an you DO NOT need to include the accessToken value in the done() callback as passport will automatically assign it to the req.user.token value for you.

I put together a full working example that uses the Authorization Code Flow in node.js using passport-bnet to pull a list of characters.

github[dot]com/viglucci/node-wow-oauth-example

If you have docker installed it should be pretty easy to clone the repo and run it as well.

1 Like

Hi!

Wow awsome replies!
Yes there were some confusion since i (Yes) followed the Blizzard Bnet git example. And since i could use the req.user.token i assumed I had the correct token. I tried using the this code below:

However, I will look into the example given and get back to you! :slight_smile:

Aaah and yes, it was the exact code, i don’t provide the accessToken in the done() callback function.

router.get(’/dashboard’, function(req, res) {

if (process.env.NODE_ENV === ‘development’) {

console.log('Development mode');

res.render('dashboard');

}

if (req.isAuthenticated()) {

characterResponse = {};

axios({

  method: 'get',

  url: 'https://eu.api.blizzard.com/wow/user/characters',

  headers: { Authorization: 'Bearer ' + req.user.token }

})

.then(response => {

  console.log(response);

  console.log(response.data);

  characterResponse = JSON.stringify(response.data);

})

.catch(err => {

  characterResponse = err;

  console.log("Could not receive characters " + err);

})

.finally(() => {

})

axios({

  method: 'get',

  url: 'https://eu.battle.net/oauth/check_token?:region=eu&token=' + req.user.token,

})

.then(response => {

  console.log(response);

  console.log(response.data);

})

.catch(err => {

  console.log("Could not validate token " + err);

})

res.render('dashboard', {

  user: req.user,

  response: characterResponse

});

} else {

res.redirect('/');

}

And I will also provide the token validation that happens in here:
_currentUrl: ‘https://eu.battle.net/oauth/check_token?:region=eu&token=THE ACCESS TOKEN’
2019-12-30T09:00:54.054363+00:00 app[web.1]: },
2019-12-30T09:00:54.054365+00:00 app[web.1]: [Symbol(kNeedDrain)]: false,
2019-12-30T09:00:54.054366+00:00 app[web.1]: [Symbol(isCorked)]: false,
2019-12-30T09:00:54.054368+00:00 app[web.1]: [Symbol(kOutHeaders)]: [Object: null prototype] {
2019-12-30T09:00:54.054369+00:00 app[web.1]: accept: [Array],
2019-12-30T09:00:54.054371+00:00 app[web.1]: ‘user-agent’: [Array],
2019-12-30T09:00:54.054372+00:00 app[web.1]: host: [Array]
2019-12-30T09:00:54.054374+00:00 app[web.1]: }
2019-12-30T09:00:54.054375+00:00 app[web.1]: },
2019-12-30T09:00:54.054376+00:00 app[web.1]: data: {
2019-12-30T09:00:54.054378+00:00 app[web.1]: exp: 1577782853,
2019-12-30T09:00:54.054379+00:00 app[web.1]: user_name: ‘MY USER ID’,
2019-12-30T09:00:54.054381+00:00 app[web.1]: authorities: [ ‘IS_AUTHENTICATED_FULLY’, ‘ROLE_USER’ ],
2019-12-30T09:00:54.054382+00:00 app[web.1]: client_id: ‘MY ID’,
2019-12-30T09:00:54.054383+00:00 app[web.1]: scope: []
2019-12-30T09:00:54.054385+00:00 app[web.1]: }
2019-12-30T09:00:54.054386+00:00 app[web.1]: }
2019-12-30T09:00:54.054387+00:00 app[web.1]: {
2019-12-30T09:00:54.054389+00:00 app[web.1]: exp: 1577782853,
2019-12-30T09:00:54.054390+00:00 app[web.1]: user_name: ‘MY USER ID’,
2019-12-30T09:00:54.054391+00:00 app[web.1]: authorities: [ ‘IS_AUTHENTICATED_FULLY’, ‘ROLE_USER’ ],
2019-12-30T09:00:54.054393+00:00 app[web.1]: client_id: ‘MY CLIENT ID’,
2019-12-30T09:00:54.054395+00:00 app[web.1]: scope: []
2019-12-30T09:00:54.054396+00:00 app[web.1]: }
2019-12-30T09:00:54.230530+00:00 app[web.1]: Could not receive characters Error: Request failed with status code 403

As seen in here, (I removed actual access token and ID ) the scope returns nothing. Otherwise it looks nice ?

I have been going through the code and cannot find more differences than different node modules. Im not using any sessionstore, cookieparser, bluebird, redis or morgan. I dont believe however that they would be required since i receive a 403 unauthorized error.

What seems strange is that when i try the API from blizzards own site, when logged in, (which means im already authorized to their site) and then providing app id and secret to “try out”. I get the same 403 unauthorized error…

Any thoughts on that? :S Reallyconfused here!

EDIT – Been adding the oauth client from the example. at least now i see this error in the heroku log:

StatusCodeError: 403 - {“error”:“insufficient_scope”,“error_description”:“Insufficient scope for this resource”,“scope”:“wow.profile profile”}

That is strange. Can you try going into your authorized applications (https://account.blizzard.com/connections#authorized-applications) on your blizzard account, remove them and re-authorize just to be sure ?

After doing this try to fetch your characters on the official API docs again.

Also make sure at least one of your characters have signed in and out of the game in the past 2 months and it is above level 10.

1 Like

omg…
THANK you @Schiller for this information.
My application were already authorized in my account with completely wrong rights. Ive been developing the application rapidly and have NOT been resetting it from my blizzard account!

I removed the authorized app
Tried myown app again

Result: Got all my characters instantly! :smiley:

Haha one week of learning node js to use passport bnet and setup an application. One week of trying to resolve fetch characters…

You sir, made my day!

1 Like