Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
3 years ago
Solved

Issues with dynamic token retrieval "query. DataSource.Error: Web.Contents failed to get contents "

I am trying to integrate an REST API source to power bi, the goal is to have it incrementally refresh, but the operations for the REST API uses dynamic access tokens. So I need to make a post functio...
  • Anonymous's avatar
    Anonymous
    3 years ago

    Hi Anonymous - you just need to get the syntax correct for Power BI to work, but it is difficult to follow with see what Postman is doing (with the sensitive information removed).  Here is an example using Power BI REST API with Service Principal:

     

     

    ##This is the structure of the HTTP REST API Call
    
    POST https://login.windows.net/{#tenant id}/oauth2/token
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials&resource={#resource}&client_id={#client id}&client_secret={#client secret}
    

     

     

     Now look at the Power BI Version - This helpfully because you can see all the intermediate steps results before the APICall fails because there is no Client ID, Secret or Tenant.  Note this works because of the Content Type requirements defined in the header, and the structure for bodystring including grant_type is often used.

     

     

    ##This is the Power BI Query Script
    
    let
        ClientID = "<clientid>",
        Secret = "<clientsecret>",
        TenantID = "<tenantid>",
        Resource = "<resource>",    
        
        BaseURL = "https://login.windows.net/" & TenantID & "/oauth2/token",
    
        BodyString = "grant_type=client_credentials&resource=" & Resource  & "&client_id=" & ClientID & "&client_secret=" & Secret,
    
        Body = Text.ToBinary(BodyString),
    
        APICall = Web.Contents(
                    BaseURL,
                    [
                        Headers = [#"Content-Type" = "application/x-www-form-urlencoded"],
                        Content = Body
                    ]
        ),
    
        OpenFile = Json.Document(APICall),
    
        GetToken = OpenFile[access_token]
    in
        GetToken

     

     

    The result is the Token to use in the next Web Call, which I believe you show this is working.


    If your requires a Json file in the body, try something like this to preview the Json file before including in the body.

     

    let
        Source = Json.FromValue([username="<Useranme>", password="<Password>"]),
        #"Preview Json" = Text.FromBinary(Source)
    in
        #"Preview Json"