【问题标题】:onedrive does not return refresh token even with 'offline_access' scope即使具有“offline_access”范围,onedrive 也不会返回刷新令牌
【发布时间】:2022-01-12 05:41:33
【问题描述】:

我正在尝试获取用户令牌以将一个驱动器集成到我正在构建的 APP 中

我首先得到 auth URL,这里是端点实现

const pca = new msal.ConfidentialClientApplication(config);
exports.getAuthUrl = (req, res) => {
  const authCodeUrlParameters = {
    scopes: ['user.read', 'files.readwrite', 'offline_access'],

    redirectUri: 'https://localhost:8080/onedrive',
  };
  // get url to sign user in and consent to scopes needed for application
  pca
    .getAuthCodeUrl(authCodeUrlParameters)
    .then((response) => {
      res.status(200).send(response);
    })
    .catch((error) => console.log(JSON.stringify(error)));
};

然后使用我在客户端身份验证成功后返回的代码作为参数传递到第二个端点以获取令牌

exports.getToken = (req, res) => {
  const tokenRequest = {
    code: req.query.code,
    scopes: ['user.read', 'files.readwrite', 'offline_access'],

    redirectUri: 'https://localhost:8080/onedrive',
  };

  pca
    .acquireTokenByCode(tokenRequest)
    .then((response) => {
      console.log('\nResponse: \n:', response);
      res.status(200).send(response);
    })
    .catch((error) => {
      console.log(error);
      res.status(500).send(error);
    });
};

因此,正如官方文档中所述,如果您添加了 offline_access 范围,您将获得一个刷新令牌

有人有这方面的经验吗?我用了这两个库,部分代码微软已经提供了const msal = require('@azure/msal-node');

【问题讨论】:

    标签: node.js api onedrive


    【解决方案1】:

    这里是如何获取刷新和访问令牌..

    /*
     * Copyright (c) Microsoft Corporation. All rights reserved.
     * Licensed under the MIT License.
     */
    const express = require("express");
    const msal = require('@azure/msal-node');
    
    const SERVER_PORT = process.env.PORT || 3000;
    const REDIRECT_URI = "http://localhost:3000/redirect";
    
    // Before running the sample, you will need to replace the values in the config, 
    // including the clientSecret
    const config = {
        auth: {
            clientId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            authority: "https://login.microsoftonline.com/84fb56d3-e15d-4ae1-acd7-cbf83c4c0af3",
            clientSecret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        },
        system: {
            loggerOptions: {
                loggerCallback(loglevel, message, containsPii) {
                    console.log(message);
                },
                piiLoggingEnabled: false,
                logLevel: msal.LogLevel.Verbose,
            }
        }
    };
    
    // Create msal application object
    const pca = new msal.ConfidentialClientApplication(config);
    
    // Create Express App and Routes
    const app = express();
    
    app.get('/', (req, res) => {
        const authCodeUrlParameters = {
            scopes: ["user.read","offline_access"],
            redirectUri: REDIRECT_URI,
            prompt:'consent'
        };
        // get url to sign user in and consent to scopes needed for application
        pca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
            res.redirect(response);
        }).catch((error) => console.log(JSON.stringify(error)));
    });
    
    app.get('/redirect', (req, res) => {
        const tokenRequest = {
            code: req.query.code,
            scopes: ["user.read","offline_access"],
            redirectUri: REDIRECT_URI,
            accessType: 'offline',
        };
        pca.acquireTokenByCode(tokenRequest).then((response) => {
            const accessToken = response.accessToken;
            const refreshToken = () => {
                const tokenCache = pca.getTokenCache().serialize();
                const refreshTokenObject = (JSON.parse(tokenCache)).RefreshToken
                const refreshToken = refreshTokenObject[Object.keys(refreshTokenObject)[0]].secret;
                return refreshToken;
            }
            const tokens = {
                accessToken,
                refreshToken:refreshToken()
            }
            console.log(tokens)
            res.sendStatus(200);
        }).catch((error) => {
            console.log(error);
            res.status(500).send(error);
        });
    });
    
    
    app.listen(SERVER_PORT, () => console.log(`Msal Node Auth Code Sample app listening on port ${SERVER_PORT}!`))
    

    【讨论】:

    • 在调用 'acquireTokenByCode' 后,'pca' 现在有了刷新令牌。 const tokenCache = pca.getTokenCache().serialize(); const refreshTokenObject = (JSON.parse(tokenCache)).RefreshToken const refreshToken = refreshTokenObject[Object.keys(refreshTokenObject)[0]].secret;
    【解决方案2】:

    好吧,经过几天的研究,我发现 msal-node 在设计上并未向最终用户公开刷新令牌。当您需要新的访问令牌时,它会在内部存储和使用。您应该在每次需要访问令牌时调用acquireTokenSilent,msal-node 将通过向您返回缓存的令牌或使用刷新令牌来获取新的访问令牌来管理令牌。 所以我所做的实际上是直接调用微软提供的端点 您应该首先使用此文档中提供的 URL [https://docs.microsoft.com/en-us/onedrive/developer/rest-api/getting-started/msa-oauth?view=odsp-graph-online][1] 获取代码 获取代码并将其传递到下一个 enpoint 中

    exports.getToken = async (req, res) => {
      request.post(
        'https://login.live.com/oauth20_token.srf',
        {
          form: {
            code: req.body.code,
            client_id: 'CLIENT-ID',
            redirect_uri: 'REDIRECT-URI',
            client_secret: 'CLIENT-SECRET',
            grant_type: 'authorization_code',
          },
        },
        async function (err, httpResponse, body) {
          if (err) {
            res.status(500).send({ Message: err.message });
          } else {
            let response = JSON.parse(body);
           res.status(200).send({ Body: JSON.parse(body) });
          }
        }
      );
    };
    

    这就是我让它工作的方式,使用 msal 没有办法

    【讨论】:

    • 我阅读了 msal-node 文档,他们的 bing ads api 文档,但找不到解决方案,但在这里你用这个答案拯救了我们!谢谢!!
    • 有办法做到这一点。在调用 'acquireTokenByCode' 后,'pca' 现在有了刷新令牌。 const tokenCache = pca.getTokenCache().serialize();常量 refreshTokenObject = (JSON.parse(tokenCache)).RefreshToken 常量 refreshToken = refreshTokenObject[Object.keys(refreshTokenObject)[0]].secret;在下面查看我的答案
    猜你喜欢
    • 2011-05-11
    • 1970-01-01
    • 2023-02-02
    • 2020-09-16
    • 2020-10-10
    • 2020-05-18
    • 1970-01-01
    • 2019-10-11
    • 2017-05-08
    相关资源
    最近更新 更多