在使用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));
});
});
});
}
您需要在应用程序中使用适当的令牌验证和令牌更新策略实施AcquiretokenSilent。基本上,您需要在调用图形api之前验证令牌是否已过期。您可以在此处阅读有关刷新令牌的信息。
让我解释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可能会失败 - 例如,用户的密码已过期。您的应用程序可以通过两种方式处理此异常:
希望能帮助到你。