Adding HttpRequestMessage logging handler causes unauthorized call
LockTar opened this issue · 7 comments
I'm trying to upgrade to v5 of the .NET SDK. In v4 we have a handler that logs the HttpRequestMessage.
The code is slightly changed in v5 in comparison with v4.
I now following the documentation in the repo and following the documentation in the Microsoft docs.
I think the documentation of Microsoft docs is better because the documentation here in the repository uses an overload of GraphClientFactory.CreateDefaultHandlers(authenticationProvider);
that doesn't exist anymore.
So I'm following the Microsoft docs with the following code:
// https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var authProvider = new AzureIdentityAuthenticationProvider(clientSecretCredential, scopes);
var handlers = GraphClientFactory.CreateDefaultHandlers();
// Add logging handler before the compression handler. Compression handler is created by CreateDefaultHandlers()
HttpRequestMessageLoggingHandler loggingHandler = new();
handlers.Insert(0, loggingHandler);
var httpClient = GraphClientFactory.Create(handlers);
var graphClient = new Microsoft.Graph.Beta.GraphServiceClient(httpClient, authProvider);
Simple logging handler:
public class HttpRequestMessageLoggingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken)
{
// log the request before it goes out.
Console.WriteLine($"Sending request => method: '{httpRequest.Method.Method}', uri: '{httpRequest.RequestUri?.AbsoluteUri}'");
// Always call base.SendAsync so that the request is forwarded through the pipeline.
HttpResponseMessage httpResponse = await base.SendAsync(httpRequest, cancellationToken);
// log the response as it comes back.
Console.WriteLine(
$"Received response => httpStatusCode: {(int)httpResponse.StatusCode}, reason: '{httpResponse.ReasonPhrase}'");
return httpResponse;
}
}
Expected behavior
Getting log of the request through my HttpRequestMessageLoggingHandler and result of the call that I make to the MS Graph.
Actual behavior
- Documentation is not up to date because of missing overload
GraphClientFactory.CreateDefaultHandlers(authenticationProvider);
. - Getting 401, InvalidAuthenticationToken, Access token is empty. message with above code.
I think the Authprovider not used/set???? Followed this documentation of the Microsoft Docs.
Steps to reproduce the behavior
Follow above code to create graph service client and make a call to an endpoint. You will get a 401.
User? user = await graphClient.Me.GetAsync();
I tested a bit more....
When I change in the above code:
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var authProvider = new AzureIdentityAuthenticationProvider(clientSecretCredential, scopes);
to:
var credential = new DefaultAzureCredential();
TokenProvider accessTokenProvider = new TokenProvider(credential);
var authProvider = new BaseBearerTokenAuthenticationProvider(accessTokenProvider);
everything is working...
So why isn't any accesstoken set when you use ClientSecretCredential
with AzureIdentityAuthenticationProvider
?
Thanks for raising this @LockTar
#623 has been created to fix the documentation bug.
To help us narrow down the issue, does this issue still persist when you create the authprovider as below?
var authProvider = new Microsoft.Graph.Authentication.AzureIdentityAuthenticationProvider(clientSecretCredential, scopes);
Thanks for raising this @LockTar
microsoftgraph/microsoft-graph-docs#623 has been created to fix the documentation bug.
Your welcome!
To help us narrow down the issue, does this issue still persist when you create the authprovider as below?
var authProvider = new Microsoft.Graph.Authentication.AzureIdentityAuthenticationProvider(clientSecretCredential, scopes);
I don't see any difference with my code? But still tested your line and I got the same 401 response. Acces token is empty.
@andrueastman See my sample project for more information:
https://github.com/LockTar/Microsoft-Graph-With-MSI-Sample/blob/organization-branding/Core/Helpers/GraphClientHelper.cs#L53-L74
Hey @LockTar,
Looks like the scopes parameter is passed incorrectly in your scenario. As you are using the ClientSecretCredential
you can safely omit it and the SDK will prepopulate the default scopes for you.
var authProvider = new Microsoft.Graph.Authentication.AzureIdentityAuthenticationProvider(clientSecretCredential);
otherwise specify the parameter name as the second parameter for the authProvider is the allowedHosts
var authProvider = new Microsoft.Graph.Authentication.AzureIdentityAuthenticationProvider(clientSecretCredential, scopes: scopes);
Hey @LockTar,
Looks like the scopes parameter is passed incorrectly in your scenario. As you are using the
ClientSecretCredential
you can safely omit it and the SDK will prepopulate the default scopes for you.var authProvider = new Microsoft.Graph.Authentication.AzureIdentityAuthenticationProvider(clientSecretCredential);otherwise specify the parameter name as the second parameter for the authProvider is the
allowedHosts
var authProvider = new Microsoft.Graph.Authentication.AzureIdentityAuthenticationProvider(clientSecretCredential, scopes: scopes);
@andrueastman I see what's happening. Your change fixed it for me. I tested both. Thanks for the help!
But I understand why this was happening in my code because this documentation is wrong as well. I copied it from that. Because that doc is wrong and because the second parameter is of the same type it went wrong. That doc should be updated as well so everything is up to date!
Thanks for the feedback there. That should be resolved with https://github.com/microsoftgraph/microsoft-graph-docs/pull/20565