Reputation: 103
I'm developing a SPA app in React that needs to integrate with AzureAD and the GraphAPI (implicit flow).
My question is very similar to: ADAL.js - Obtaining Microsoft Graph Access Token with id_token ... but the answer doesn't show me enough code to get me on my way.
So far, using just adal.js (v1.0.14), I can login & get an id_token, but I can't figure out how to use it to get access to make Graph API calls.
UPDATE: I know I'm correctly registered with the Azure portal, because I was able to login and get recent docs without adal.js or any lib ... just using home-made ajax calls.
Here's my code, which does the login/redirect, and then tries to get my recent docs:
// Initial setup
var adalCfg = {
instance : 'https://login.microsoftonline.com/',
tenant : 'common',
clientId : 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
postLogoutRedirectUri : window.location.origin,
extraQueryParameter : 'scope=Mail.ReadWrite+Files.Read+Files.ReadWrite+User.ReadBasic.All' // Is this the proper way to specify what resources I need access to?
};
var authContext = new Adal(adalCfg);
if(!authContext.getCachedUser()) {
authContext.login(); // redirects MS login page successfully
}
// Check For & Handle Redirect From AAD After Login
var isCallback = authContext.isCallback(window.location.hash); // Checks if the URL fragment contains access token, id token or error_description.
if(isCallback) {
authContext.handleWindowCallback(); // extracts the hash, processes the token or error, saves it in the cache and calls the registered callbacks with the result.
}
if (isCallback && !authContext.getLoginError()) {
window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST); // redirects back to /
}
// Try to get my recent docs - FAILS with InvalidAuthenticationToken error
// UDPATED authContext.acquireToken(authContext.config.clientId, function (error, token) {
authContext.acquireToken('https://graph.microsoft.com', function (error, token) {
$.ajax({
url: 'https://graph.microsoft.com/v1.0/me/drive/recent',
headers:{'authorization':'Bearer '+ token},
type:'GET',
dataType:'json'
}).done(function(res) {
console.log(res['value']);
});
});
What have I got wrong?
Update 2: I changed acquireToken
per Fei's answer, but now when adal silently gets an access token for my resource, it fails to pass it to my API call.
Updated code:
adalCfg.endpoints.graphApiUri = "https://graph.microsoft.com";
authContext.acquireToken(adalCfg.endpoints.graphApiUri, function (errorDesc, token, error) {
console.log('errorDesc = ' + errorDesc)
console.log('token = ' + token)
console.log('error = ' + error)
$.ajax({
url: adalCfg.endpoints.graphApiUri + '/v1.0/me/drive/recent',
headers:{'authorization':'Bearer '+ token},
type:'GET',
dataType:'json'
}).done(function(res) {
console.log(res['value']);
});
});
And console output:
The image shows the req for a token, which appears to succeed, because the next GET contains the access_token
in the hash. However, acquireToken
passes a null
token to my Graph API call.
However, if I manually grab the access token out of the hash, I can successfully make the Graph API call.
Why doesn't adal pass the access token to my API call? It came back and is valid.
Upvotes: 3
Views: 8721
Reputation: 14649
To call the Microsoft Graph, we need to get the specific token for this resource. Based on the code you were acquire the token using the authContext.config.clientId
.
If you register the app on Azure portal, to get the access token for the Microsoft Graph, you need to replace authContext.config.clientId
with https://graph.microsoft.com
.
And to call the REST sucessfully, we need to make sure having the enough permission. For example, to list recent files, one of the following scopes is required:Files.Read
,Files.ReadWrite
,Files.Read.All
,Files.ReadWrite.All
,Sites.Read.All
,Sites.ReadWrite.All
(refer here).
<html>
<head>
<script src="\node_modules\jquery\dist\jquery.js"></script>
<script src="node_modules\adal-angular\lib\adal.js"></script>
</head>
<body>
<button id="login"> login</button>
<button id="clickMe">click me</button>
<script>
$(function () {
var endpoints = {
"https://graph.microsoft.com": "https://graph.microsoft.com"
};
window.config = {
tenant: 'xxxx.onmicrosoft.com',
clientId: 'xxxxxxxxxxxxxxxxx',
endpoints: endpoints
};
window.authContext = new AuthenticationContext(config);
$("#login").click(function () {
window.authContext.login();
});
$("#clickMe").click(function () {
var user = window.authContext.getCachedUser();
console.log(user);
window.authContext.acquireToken('https://graph.microsoft.com', function (error, token) {
console.log(error);
console.log(token);
$.ajax({
url: 'https://graph.microsoft.com/v1.0/me/',
headers:{'authorization':'Bearer '+ token},
type:'GET',
dataType:'json'
}).done(function(res) {
console.log(res['userPrincipalName']);
});
});
}
);
function init(){
if(window.location.hash!="")
window.authContext.handleWindowCallback(window.location.hash);
}
init();
});
</script>
</body>
</html>
Upvotes: 3