2

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"?

Akshay
  • 85
  • 9
  • I used to have the same idea as yours that just sending an AJAX request to get the access token. And certainly I failed. I think [this doc](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-javascript) will help you. – Tiny Wang Dec 17 '20 at 15:10

2 Answers2

1
<!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

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
  • Thanks for your response Tiny-wa. By using this solution I stuck on an error. The error is "InteractionRequiredAuthError: AADSTS65001: The user or administrator has not consented to use the application with ID 'xxxxxx' named 'xxxxx powerBI Embed Test1'. Send an interactive authorization request for this user and resource." can you please help me out? – Akshay Dec 26 '20 at 17:42
  • My code uses implicite grant flow to get an access token and call an API, so after creating an azure ad application, I also need to set api permission and make sure that 'access token' has been checked in authentication tag. – Tiny Wang Dec 27 '20 at 14:38
  • I solved it. It is necessary to add mail.read permission in Microsoft graph API. Just login with your admin account and go to app registration then select API permissions and click on add permission – Akshay Dec 27 '20 at 18:27
  • I got access token but this access token failed to get embed token.It returns 403 forbidden – Akshay Dec 27 '20 at 18:30
  • 403 means your app has no permission to access API. So if you wanna to call 'powerbi-UserState.ReadWrite.All', then you need to add this API permission, next to get access token with this scope, after that you can do it. – Tiny Wang Dec 28 '20 at 02:03
  • Any ideas? Or more details? – Tiny Wang Dec 28 '20 at 02:21
  • Hey, Tiny-wa you made my day. It works for me. Thanks a lot. – Akshay Dec 28 '20 at 13:10
  • I'm glad to hear that, hope your program stay far away from bug. hh , good day. – Tiny Wang Dec 28 '20 at 15:06
0

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);
    })
  })
}
Satya V
  • 3,811
  • 1
  • 6
  • 9