Akshay
Akshay

Reputation: 85

Failed to load response data when tried to get access token from azure using JavaScript

I want to get an Access token for my registered application on azure. To do so I wrote a piece of code to hit the rest-API.

This is my code:

<html>
<head>
  <title>Test</title>   
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.12/js/adal.min.js"></script>
  <script src="/static/powerbi.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>        
  </head>
<body>
  <div id="captionArea">
    <h1>Power BI Embed test</h1>
  </div>
  <div id="embedContainer" style="height:500px">
  </div> 
  <script>
    (function () {

    var reportId = 'xxxxxxxxxx'
    var groupId  = 'xxxxxxxxxx'   //workspace_id
    var datasetId = 'xxxxxxxxxx'
    
    
   var settings = {
  "url": "https://login.microsoftonline.com/common/oauth2/token",
  "method": "POST",
  "crossDomain": true,
  "dataType": 'jsonp',
  "timeout": 0,
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "data": {
    "client_id": "********",
    "username": "***",
    "password": "***",
    "grant_type": "password",
    "resource": "https://analysis.windows.net/powerbi/api"
  }
};

$.ajax(settings).done(function (response) {
  console.log(response);
}); 
}());
  </script>
</body>
</html>

and after this, I got a response. In the console, under the header section, I got status: 200 and request method: GET but in my code, the request method is "POST", and In the response section, it shows "This request has no response data available" :

enter image description here

enter image description here

I don't know, why I am not getting any response and how my request method changes from "POST" to "GET"?

Upvotes: 2

Views: 1669

Answers (2)

Tiny Wang
Tiny Wang

Reputation: 15991

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="js/msal.js"></script>
    </head>
    <body>
        <div style="font-size: 12px;">
            this sample used implicit grant flow to get access token
        </div>
            <div style="margin-top: 15px; background-color: #DDDDDD;">
                <button type="button" id="signIn" onclick="signIn()">Sign In</button>
                <button type="button" id="getAccessToken" onclick="getAzureAccessToken()">getAccessToken</button>
                <button type="button" id="accessApi" onclick="accessApi()">getApiResponse</button>
                <h5 class="card-title" id="welcomeMessage">Please sign-in to see your profile and read your mails</h5>
                <div>
                    <div>
                        accesstoken :
                        <div id="accesstoken">
                            
                        </div>
                    </div>
                    <div id="">
                        api response :
                        <div id="json">
                            
                        </div>
                    </div>
                </div>
            </div>
            <script type="text/javascript">
                const msalConfig = {
                    auth: {
                        clientId: "<applicationId>",
                        authority: "https://login.microsoftonline.com/<tenantId>",
                        redirectUri: "http://localhost:8848/Demo0819/new_file.html",
                    },
                    cache: {
                        cacheLocation: "sessionStorage", // This configures where your cache will be stored
                        storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
                    }
                };
        
                const loginRequest = {
                    scopes: ["openid", "profile", "User.Read"]
                };
                //scope for getting accesstoken
                const AzureMgmtScops ={
                    scopes:["https://management.azure.com/user_impersonation"]
                }
                //used for calling api 
                const apiConf = {
                    endpoint:"https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.CostManagement/query?api-version=2019-11-01"
                };
                
                let accessToken = '';
                const myMSALObj = new Msal.UserAgentApplication(msalConfig);
        
                function signIn() {
                    myMSALObj.loginPopup(loginRequest)
                        .then(loginResponse => {
                            console.log("id_token acquired at: " + new Date().toString());
                            console.log(loginResponse);
        
                            if (myMSALObj.getAccount()) {
                                showWelcomeMessage(myMSALObj.getAccount());
                            }
                        }).catch(error => {
                            console.log(error);
                        });
                }
        
                function showWelcomeMessage(account) {
                    document.getElementById("welcomeMessage").innerHTML = `Welcome ${account.name}`;
                }
        
                function getAzureAccessToken(){
                    myMSALObj.acquireTokenSilent(AzureMgmtScops).then(tokenResponse => {
                        showAccesstoken(tokenResponse.accessToken)
                        accessToken = tokenResponse.accessToken;
                        // console.info("======the accesstoken is ======:"+tokenResponse.accessToken);
                        // callMSGraph(apiConf.endpoint, tokenResponse.accessToken, showResult);
                    }).catch(function (error) {
                         console.log(error);
                    })
                }
                
                function accessApi(){
                    callMSGraph(apiConf.endpoint, accessToken, showResult);
                }
        
                function callMSGraph(endpoint, token, callback) {
                    const data = {
                        "type": "Usage",
                        "timeframe": "MonthToDate",
                        "dataset": {
                            "granularity": "Daily",
                        }
                    }
                    const headers = new Headers();
                    const bearer = `Bearer ${token}`;
        
                    headers.append("Content-Type", "application/json");
                    headers.append("Authorization", bearer);
        
                    const options = {
                        body: JSON.stringify(data),
                        method: "POST",
                        headers: headers
                    };
        
                    console.log('request made to Graph API at: ' + new Date().toString());
        
                    fetch(endpoint, options)
                        .then(response => response.json())
                        .then(response => callback(response, endpoint))
                        .catch(error => console.log(error))
                }
                
                function showAccesstoken(data){
                    document.getElementById("accesstoken").innerHTML = JSON.stringify(data, null, 2);
                }
                
                function showResult(data){
                    document.getElementById("json").innerHTML = JSON.stringify(data, null, 2);
                }
            </script>
    </body>
</html>

=========UPDATE======

E.g.

I wanna to call this api to get information 'https://api.powerbi.com/v1.0/myorg/groups' , so add api permission first. enter image description hereenter image description here

Next step is to get access token with this scope. enter image description here

With this access token, call the api then it will work. enter image description here

Upvotes: 1

Satya V
Satya V

Reputation: 4164

You have data type as JSONP. It simply creates a element to fetch data which has to be a GET request.

Reference : Send data using POST to JSONP request

How to use type: "POST" in jsonp ajax call

You could possible get the response by issuing a POST request and then use the obtained access token for the embed token.

Some thing like below :

var getAccessToken = function {

  return new Promise(function(resolve, reject) {

    var url = 'https://login.microsoftonline.com/common/oauth2/token';

    var username = // Username of PowerBI "pro" account - stored in config
    var password = // Password of PowerBI "pro" account - stored in config
    var clientId = // Applicaton ID of app registered via Azure Active Directory - stored in config

    var headers = {
      'Content-Type' : 'application/x-www-form-urlencoded'
    };

    var formData = {
      grant_type:'password',
      client_id: clientId,
      resource:'https://analysis.windows.net/powerbi/api',
      scope:'openid',
      username:username,
      password:password
    };

    request.post({
      url:url,
      form:formData,
      headers:headers

    }, function(err, result, body) {
      if(err) return reject(err);
      var bodyObj = JSON.parse(body);
      resolve(bodyObj.access_token);
    })
  });
}

// -------------------------------------------

var getEmbedToken = function(accessToken, groupId, reportId) {

  return new Promise(function(resolve, reject) {

    var url = 'https://api.powerbi.com/v1.0/myorg/groups/' + groupId + '/reports/' + reportId + '/GenerateToken';

    var headers = {
      'Content-Type' : 'application/x-www-form-urlencoded',
      'Authorization' : 'Bearer ' + accessToken
    };

    var formData = {
      "accessLevel": "View"
    };

    request.post({
      url:url,
      form:formData,
      headers:headers

    }, function(err, result, body) {
      if(err) return reject(err);
      console.log(body)
      var bodyObj = JSON.parse(body);
      resolve(bodyObj.token);
    })
  })
}

Upvotes: 0

Related Questions