在使用MSAL-Angular并为Azure Active Directory图形api请求access_token时,它会使用Microsoft图形api的标记来提供令牌

问题描述 投票:0回答:1

在使用MSAL-Angular并为Azure Active Directory图形API(https://graph.windows.net/)请求access_token时,它会使用Microsoft图形api(https://graph.microsoft.com)的标记来提供令牌。

我需要调用azure活动目录图api,因为Microsoft graph api是测试版。现在,当我使用msalService获取Azure Active Directory图api的access_token时,它会给出带有微软图api的aud的令牌。当我尝试使用该令牌时,它会出现“您的访问令牌已过期”的错误。请在提交请求之前续订。即使令牌有效时间。

我使用下面的typescript代码生成access_token public async getAccessToken(endpointUri:string):Promise {

this.accessToken = '';
const scopes = this.msalService.getScopesForEndpoint(endpointUri);

return new Promise<boolean>((resolve, reject) => {
  this.msalService.acquireTokenSilent(scopes)

    .then(accessToken => {
      this.accessToken = accessToken;
      resolve(true);
      // tslint:disable-next-line: promise-function-async
    }).catch(() => {

      return this.msalService.acquireTokenPopup(scopes)
        .then(token => {

          this.accessToken = token;
          resolve(true);

        })
        .catch((error) => {
          reject(new Error(error));
        });
    });
});

}

angular azure-active-directory azure-ad-graph-api msal
1个回答
2
投票

您需要在应用程序中使用适当的令牌验证和令牌更新策略实施AcquiretokenSilent。基本上,您需要在调用图形api之前验证令牌是否已过期。您可以在此处阅读有关刷新令牌的信息。

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow#refreshing-tokens

让我解释SPA的场景,我们使用Microsoft身份验证库(MSAL)库来验证用户并使用令牌调用Azure图形api

假设这是我的索引页面

<!DOCTYPE html>
<html>
<head>
    <title>Quickstart for MSAL JS</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js"></script>
    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/0.2.3/js/msal.js"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
    <h2>Welcome to MSAL.js Quickstart</h2><br/>
    <h4 id="WelcomeMessage"></h4>
    <button id="SignIn" onclick="signIn()">Sign In</button><br/><br/>
    <pre id="json"></pre>
    <script>
        //JS code
    </script>
</body>
</html>

在标记中添加以下代码

//Pass null for default authority (https://login.microsoftonline.com/common)
var myMSALObj = new Msal.UserAgentApplication(applicationConfig.clientID, null, acquireTokenRedirectCallBack,
    {storeAuthStateInCookie: true, cacheLocation: "localStorage"});

function signIn() {
    myMSALObj.loginPopup(applicationConfig.graphScopes).then(function (idToken) {
        //Login Success
        showWelcomeMessage();
        acquireTokenPopupAndCallMSGraph();
    }, function (error) {
        console.log(error);
    });
}

function acquireTokenPopupAndCallMSGraph() {
    //Call acquireTokenSilent (iframe) to obtain a token for Microsoft Graph
    myMSALObj.acquireTokenSilent(applicationConfig.graphScopes).then(function (accessToken) {
        callMSGraph(applicationConfig.graphEndpoint, accessToken, graphAPICallback);
    }, function (error) {
        console.log(error);
        // Call acquireTokenPopup (popup window) in case of acquireTokenSilent failure due to consent or interaction required ONLY
        if (error.indexOf("consent_required") !== -1 || error.indexOf("interaction_required") !== -1 || error.indexOf("login_required") !== -1) {
            myMSALObj.acquireTokenPopup(applicationConfig.graphScopes).then(function (accessToken) {
                callMSGraph(applicationConfig.graphEndpoint, accessToken, graphAPICallback);
            }, function (error) {
                console.log(error);
            });
        }
    });
}

function graphAPICallback(data) {
    //Display user data on DOM
    var divWelcome = document.getElementById('WelcomeMessage');
    divWelcome.innerHTML += " to Microsoft Graph API!!";
    document.getElementById("json").innerHTML = JSON.stringify(data, null, 2);
}

function showWelcomeMessage() {
    var divWelcome = document.getElementById('WelcomeMessage');
    divWelcome.innerHTML += 'Welcome ' + myMSALObj.getUser().name;
    var loginbutton = document.getElementById('SignIn');
    loginbutton.innerHTML = 'Sign Out';
    loginbutton.setAttribute('onclick', 'signOut();');
}

// This function can be removed if you do not need to support IE
function acquireTokenRedirectAndCallMSGraph() {
    //Call acquireTokenSilent (iframe) to obtain a token for Microsoft Graph
    myMSALObj.acquireTokenSilent(applicationConfig.graphScopes).then(function (accessToken) {
      callMSGraph(applicationConfig.graphEndpoint, accessToken, graphAPICallback);
    }, function (error) {
        console.log(error);
        //Call acquireTokenRedirect in case of acquireToken Failure
        if (error.indexOf("consent_required") !== -1 || error.indexOf("interaction_required") !== -1 || error.indexOf("login_required") !== -1) {
            myMSALObj.acquireTokenRedirect(applicationConfig.graphScopes);
        }
    });
}

function acquireTokenRedirectCallBack(errorDesc, token, error, tokenType) {
    if (tokenType === "access_token") {
        callMSGraph(applicationConfig.graphEndpoint, token, graphAPICallback);
    } else {
        console.log("token type is:"+tokenType);
    }
}


// Browser check variables
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
var msie11 = ua.indexOf('Trident/');
var msedge = ua.indexOf('Edge/');
var isIE = msie > 0 || msie11 > 0;
var isEdge = msedge > 0;

//If you support IE, our recommendation is that you sign-in using Redirect APIs
//If you as a developer are testing using Microsoft Edge InPrivate mode, please add "isEdge" to the if check
if (!isIE) {
    if (myMSALObj.getUser()) {// avoid duplicate code execution on page load in case of iframe and popup window.
        showWelcomeMessage();
        acquireTokenPopupAndCallMSGraph();
    }
} else {
    document.getElementById("SignIn").onclick = function () {
        myMSALObj.loginRedirect(applicationConfig.graphScopes);
    };
    if (myMSALObj.getUser() && !myMSALObj.isCallback(window.location.hash)) {// avoid duplicate code execution on page load in case of iframe and popup window.
        showWelcomeMessage();
        acquireTokenRedirectAndCallMSGraph();
    }
}

用户第一次单击“登录”按钮后,signIn方法将调用loginPopup以登录用户。此方法导致使用Microsoft Azure Active Directory v2.0端点打开弹出窗口,以提示和验证用户的凭据。成功登录后,用户将被重定向回原始index.html页面,并收到一个令牌,由msal.js处理,并缓存令牌中包含的信息。此令牌称为ID令牌,包含有关用户的基本信息,例如用户显示名称。如果您计划将此令牌提供的任何数据用于任何目的,则需要确保后端服务器验证此令牌,以确保将令牌发给应用程序的有效用户。

本指南生成的SPA调用acquireTokenSilent和/或acquireTokenPopup来获取用于查询Microsoft Graph API以获取用户配置文件信息的访问令牌。

调用acquireTokenPopup(范围)会导致弹出窗口(或acquireTokenRedirect(范围)导致用户重定向到Azure Active Directory v2.0端点),用户需要通过确认其凭据进行交互,同意所需资源,或完成双因素身份验证。

acquireTokenSilent方法无需任何用户交互即可处理令牌获取和续订。在首次执行loginPopup(或loginRedirect)之后,acquireTokenSilent是常用于获取用于访问受保护资源以用于后续调用的令牌的方法 - 因为对请求或续订令牌的调用是以静默方式进行的。在某些情况下,acquireTokenSilent可能会失败 - 例如,用户的密码已过期。您的应用程序可以通过两种方式处理此异常:

  1. 立即调用acquireTokenPopup,这会提示用户登录。此模式通常用于在线应用程序中,用户可以使用的应用程序中没有未经身份验证的内容。此指导设置生成的样本使用此模式。
  2. 应用程序还可以向用户显示需要交互式登录的可视指示,以便用户可以选择正确的登录时间,或者应用程序可以在以后重试acquireTokenSilent。当用户可以使用应用程序的其他功能而不会中断时,通常会使用此方法

希望能帮助到你。

© www.soinside.com 2019 - 2024. All rights reserved.