Battle.net API 使用 OAuth Token 返回 401 错误

Posted

技术标签:

【中文标题】Battle.net API 使用 OAuth Token 返回 401 错误【英文标题】:Battle.net API returns 401 Error using OAuth Token 【发布时间】:2019-05-31 18:06:37 【问题描述】:

我在 Battle.net API 上使用 Nodejs 和 express 来生成 Oauth 令牌。 https://develop.battle.net/documentation/guides/using-oauth

生成令牌本身是有效的,因为它会返回给我令牌。但是当我使用代码向他们的 API 发出请求时,例如:

https://eu.api.blizzard.com/wow/guild/Malfurion/The%20new%20Dimension?fields=members&locale=de_DE&access_token=HEREISMYTOKEN

我收到 401 Unauthorized Error Response,调试日志:

 url:
      'https://eu.api.blizzard.com/wow/guild/Malfurion/The%20new%20Dimension?fields=members&locale=de_DE&access_token=HEREISMYTOKEN',
     status: 401,
     statusText: 'Unauthorized',
     headers: Headers  [Symbol(map)]: [Object]  

我正在尝试通过 fetch() 获取公会成员。

我已经试过了:

创建新应用程序(使用新的客户端密码和 ID)

在战网设置中设置所有可能的回调 url:

https://localhost/ http://localhost/ https://localhost:443/ http://localhost:443/ https://localhost/auth/bnet/callback http://localhost/auth/bnet/callback https://localhost:443/auth/bnet/callback http://localhost:443/auth/bnet/callback

通过“试用 api”(https://develop.battle.net/documentation/api-reference/world-of-warcraft-community-api) 手动创建令牌,您可以在其中输入客户端 ID 和机密,然后获取临时令牌。那个工作,也在我的应用程序中。

您可以比较这两个网址的响应(只需使用您的浏览器):

第一个(在我的应用程序中生成):https://eu.api.blizzard.com/wow/guild/Blackmoore/The%20new%20Dimension?fields=members&locale=de_DE&access_token=EU7XD8E4K9IAJKBGJSP3MDBLAVCIU2BYXS

第二(生成在战网网站上试用 API,您填写 clientid 和 secret 以测试 api):https://eu.api.blizzard.com/wow/guild/Blackmoore/The%20new%20Dimension?fields=members&locale=de_DE&access_token=US23su4g0hAeS5w3EUCkKA9MJPgJ8k8bzV

代码

server.js,简单的快递应用

var BNET_ID = "MYID";
var BNET_SECRET = "MYSECRET";

...

// Use the BnetStrategy within Passport.
passport.use(
  new BnetStrategy(
     clientID: BNET_ID,
      clientSecret: BNET_SECRET,
      scope: "wow.profile sc2.profile",
      callbackURL: "https://localhost/",
      region: "eu" ,
    function(accessToken, refreshToken, profile, done) 
      process.nextTick(function () 
        return done(null, profile);
      );
    )
);
// bnet auth routes
app.get('/auth/bnet', passport.authenticate('bnet'));

app.get('/auth/bnet/callback',
    passport.authenticate('bnet',  failureRedirect: '/' ),
    function(req, res)
        res.redirect('/');
);

controller.js

...

      const res = await fetch(`https://eu.api.blizzard.com/wow/guild/$servers[iterator]/The new Dimension?fields=members&locale=de_DE&access_token=$thetoken`).then((res) => 
        res.json();
        // for debugging, shows 401 Error
        console.log(res);
      );

...

我实际上希望得到这样的响应,因为它使用临时令牌工作:

status: 200 OK

body: 
  "lastModified": 1546676373000,
  "name": "The new Dimension",
  "realm": "Blackmoore",
  "battlegroup": "Glutsturm / Emberstorm",
  "level": 25,
  "side": 0,
  "achievementPoints": 1005,
  "members": 
(......)

我设法解决了这个问题!

非常非常老套,但我设法通过破解 oauth 回调中间件解决了这个问题,如下所示: 将我使用的 API 令牌设置为 req.user.token。

app.get('/auth/bnet/callback',
    passport.authenticate('bnet',  failureRedirect: '/?error' ),
    function(req, res) 
      req.session.bnettoken = req.user.token;

      res.redirect('/');
    
);

我怀疑我的 SessionStorage (express-session) 中也使用了“代码”或“令牌”来将当前会话存储在我的数据库中。所以我只是从请求中破解 user.token 并使用它。呼……工作时间。

【问题讨论】:

【参考方案1】:

从文档中我可以看到,您需要将令牌传递到 Authorization 标头,其值为:Bearer HEREISMYTOKEN

有关授权标头和标头的更多信息:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Headers

如何使用它的例子可以在this SO answer找到

【讨论】:

那么我在哪里设置授权标头?我以为我只是得到一个令牌,然后将其放入我的 fetch url。 因为使用我自己通过 oauth2 生成的令牌,我得到与使用任何密钥相同的错误,例如“PEPEE”,来自该的响应是 url:'eu.api.blizzard.com/wow/guild/Blackmoore/…',状态:401,statusText : '未经授权', 当您发出 HTTP 请求时,您可以将多个标头附加到请求中,在本例中为 Authorization 所以我需要在我的 fetch 中添加一些东西吗? 我添加了有关如何将标题添加到提取的链接。请看一下

以上是关于Battle.net API 使用 OAuth Token 返回 401 错误的主要内容,如果未能解决你的问题,请参考以下文章

8种至关重要OAuth API授权流与能力

从 Oauth2 DocuSign API 隐式授权获取用户信息

OAuth2.0学习(5-4)新浪开放平台-微博API-使用OAuth2.0调用API

如何验证每个用户可以使用 OAuth 和 OpenID Connect 访问哪些资源?

使用 google-api-java-oauth 的 oauth1 示例 [关闭]

使用 google-api-java-oauth 的 oauth1 示例 [关闭]