YannickRe / ms-graph-proxy-function

Azure Function that acts as a Proxy to the Microsoft Graph, for the purpose of allowing Power BI to connect to the Microsoft Graph
20 stars 10 forks source link

Object reference not set to an instance of an object. #1

Closed jumlu closed 5 years ago

jumlu commented 5 years ago

Hi, thanks for that awesome workaround. Unfortunately, I cannot get it up and running and always get the error message:

Object reference not set to an instance of an object.

I set UseApplicationPermissions to false, because otherwise I always receive a "forbidden" feedback.

Any idea what the issue might be?

YannickRe commented 5 years ago

I might be able to help out if I can get some more information:

jumlu commented 5 years ago

Thanks for your response!

If I set UseApplicationPermissions to true, I get a permission forbidden error (although I added the application to the access policy of the key vault).

2019-03-07T08:36:29.959 [Information] Executing 'MicrosoftGraphBeta' (Reason='This function was programmatically called via the host APIs.', Id=b6a001a4-2b48-4905-b253-2ef26d2eafd4)
2019-03-07T08:36:32.110 [Error] Operation returned an invalid status code 'Forbidden'
Microsoft.Azure.KeyVault.Models.KeyVaultErrorException : Operation returned an invalid status code 'Forbidden'
   at async Microsoft.Azure.KeyVault.KeyVaultClient.GetSecretWithHttpMessagesAsync(String vaultBaseUrl,String secretName,String secretVersion,Dictionary`2 customHeaders,CancellationToken cancellationToken)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.Azure.KeyVault.KeyVaultClientExtensions.GetSecretAsync(??)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.Utils.KeyVaultUtilities.GetSecretAsync(String keyVaultUri,String secretName) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\KeyVaultUtilities.cs : 21
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.Utils.AdalUtilities.GetApplicationAccessToken(String resource,String clientId,String clientSecretName,String authority,String tenantId,String keyVaultUri) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\AdalUtilities.cs : 18
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.Utils.FunctionUtilities.<>c__DisplayClass0_0.<GetAuthenticationProvider>b__0(??) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\FunctionUtilities.cs : 23
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.Utils.GraphUtilities.ExecuteGetRequest(GraphServiceClient graphClient,String graphRequestUrl) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\GraphUtilities.cs : 31
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.MicrosoftGraphProxy.<>c__DisplayClass2_0.<Run>b__0(??) at D:\home\site\repository\MicrosoftGraphProxyFunction\MicrosoftGraphProxy.cs : 33
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.Utils.SafeExecutor.Execute(??) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\SafeExecutor.cs : 17
2019-03-07T08:36:32.248 [Information] Executed 'MicrosoftGraphBeta' (Succeeded, Id=b6a001a4-2b48-4905-b253-2ef26d2eafd4)

If I switch to true, I get a "Null"-Error:

2019-03-07T08:35:01.129 [Information] Executing 'MicrosoftGraphBeta' (Reason='This function was programmatically called via the host APIs.', Id=344b9af8-8074-4b2a-8a07-51eb33152931)
2019-03-07T08:35:01.307 [Error] Object reference not set to an instance of an object.
System.NullReferenceException : Object reference not set to an instance of an object.
   at async MicrosoftGraphProxyFunction.Utils.FunctionUtilities.<>c__DisplayClass0_0.<GetAuthenticationProvider>b__1(??) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\FunctionUtilities.cs : 30
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.Utils.GraphUtilities.ExecuteGetRequest(GraphServiceClient graphClient,String graphRequestUrl) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\GraphUtilities.cs : 31
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.MicrosoftGraphProxy.<>c__DisplayClass2_0.<Run>b__0(??) at D:\home\site\repository\MicrosoftGraphProxyFunction\MicrosoftGraphProxy.cs : 33
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async MicrosoftGraphProxyFunction.Utils.SafeExecutor.Execute(??) at D:\home\site\repository\MicrosoftGraphProxyFunction\Utils\SafeExecutor.cs : 17
2019-03-07T08:35:01.396 [Information] Executed 'MicrosoftGraphBeta' (Succeeded, Id=344b9af8-8074-4b2a-8a07-51eb33152931)

Unfortunately, I cannot test with VS. I used Kudu to get the logs. On the Authentication / Authorization site, it states that Certificate Binding should be configured. Might that cause the problem?

To enable Authentication / Authorization, please ensure all your custom domains have corresponding SSL bindings, your .NET version is configured to “4.5” or higher and manage pipeline mode is set to “Integrated”

YannickRe commented 5 years ago

I'm thinking that if we fix the Null-error, we will still hit the "Operation returned an invalid status code 'Forbidden'" in both cases.

Forbidden issue:

Null reference issue:

mikebarrattvcs commented 5 years ago

I had the same issue initially, it's because I didn't RTFM properly and left the trailing '/' in the URL/URI Application entries. Once I removed these, it all worked fine! Great workaround and has saved me some headaches!

YannickRe commented 5 years ago

@mikebarrattvcs , thanks for letting me know! I just pushed a small code changes to make sure that a trailing slash can't cause those kinds of issues.

@jumlu Can you try again with the fixed code and the suggestions I provided? Let me know if you need more help.

jumlu commented 5 years ago

@mikebarrattvcs: Yeah, that was what happened to me as well and I fixed it immediately.

@YannickRe: Thanks for all your suggestions, let me answer below:

I initially tried to access the API by just calling the GET-URL in Chrome. The authorization is triggered, but a Bearer token is not used. So I installed a proxy to see what Power BI does to simulate it with Postman. Power BI is actually requesting and using the Bearer token and tries to access it that way. Intercepting the traffic revealed that Power BI sends a request including the Bearer token and gets the following response:

HTTP/1.1 401 Unauthorized
Content-Length: 58
Content-Type: text/html
WWW-Authenticate: Bearer realm="<function-url>" authorization_uri="https://login.windows.net/<tenant-id>/oauth2/authorize" resource_id="<resource-id"
X-Powered-By: ASP.NET
Date: Wed, 13 Mar 2019 21:38:57 GMT
Connection: close

You do not have permission to view this directory or page.

So I started investigating in that direction and found the a good post on stackoverflow, explaining the issue.

I then removed the trailing slash from the "Allowed Token Audiences" parameter and it worked.

I am currently writing a script based on Azure CLI in order to automate the provisioning of the workaround. As soon as I complete this, I will post it here.

Thanks for your help!

YannickRe commented 5 years ago

Good you figured it out! I already say in the installation guide to do: Allowed token audiences

You think I should make the directions more clear? I'll leave the issue open for your Azure CLI script, and close afterwards.

jumlu commented 5 years ago

Yes, I just didn't put the required importance into the trailing slash ;)

Maybe just state in the guide to remove the part '/.auth/login/aad/callback' from the URL?

YannickRe commented 5 years ago

That would work in the case that you put this in a separate function and only access it from Power BI. If you'd want to access the function through code, the original callback URL is still necessary.

Since two people have issues with slashes ;), I'll leave this open and spend some time on reworking the installation steps.

YannickRe commented 5 years ago

Made a remark about the / in the readme.md, closing this now. Thank you both for the contribution!