Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add authentication header to HTTP requests created by BrowserHttpSink? #7

Open
szmalec opened this issue Feb 14, 2020 · 2 comments

Comments

@szmalec
Copy link

szmalec commented Feb 14, 2020

I would like logs generated for an authenticated user to be sent to the server along with the user's token in the headers.
If the user signs off, log entries should be sent to the server without this token.

Scenario:
I am using Serilog.Sinks.BrowserHttp in my Blazor WASM app:

Log.Logger = new LoggerConfiguration()
    .WriteTo.BrowserHttp()
    .CreateLogger();

try {
    Log.Information("Starting app ({clientAppVersion})...", typeof(Program).Assembly.GetName().Version);
    // https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-preview-1-release-now-available/
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.Services.AddSingleton<MyCustomJwtAuthService>();
    //...
    builder.RootComponents.Add<App>("app");
    await builder.Build().RunAsync();
}
catch (Exception ex)
{
    Log.Fatal(ex, "An exception occurred while creating the WASM host");
    throw;
}

My app uses some king MyCustomJwtAuthService (which is also used in my custom AuthenticationStateProvider implementation) which holds JWT token for currently signed in user (it also silently refreshes token). This JWT token is added to headers (_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);) - so when HttpClient is used then HTTP requests are authenticated.
As I can see in sources Blazor registers in DI singleton for HttpClient, but BrowserHttpSink creates its own HttpClient instance and Authorization header added by MyCustomJwtAuthService does not affect HttpClient instance created in BrowserHttpSink - so I can not extract authenticated user data from requests perfomed by BrowserHttpSink...
I know that BrowserHttpSink accepts HttpMessageHandler as parameter but there are probably some issues related to used in Blazor WasmHttpMessageHandler (eg. see how folks are creating instances here).
Maybe it would be better for BrowserHttpSink to take a parameter of type Func<HttpClient> - so that I could somehow decide whether to provide an instance created by DI or maybe a temporary instance before the DI system produces the correct instance for me?
Although this may also not be ideal, because logs are sent to the server with a delay, so logs generated for an authenticated user can be sent after logging out ...

Any suggestions?

@accessfreelancer
Copy link

Hi, did you ever find a solution for the http message handler?

I am using blazor WASM standalone and windows authentication on my web api and need to attach the following to all my http requests. The log http request isnt working because I need to attach the same request.

I tried adding "messageHandler: new AuthorizationMessageHandler()" to the logger config but it doesnt seem to have any affect.

public class AuthorizationMessageHandler : DelegatingHandler
{
protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
return base.SendAsync(request, cancellationToken);
}
}

@mtavares628
Copy link
Contributor

Just checking if there is any update with this question. I'm in the same boat trying to figure out how to properly instantiate the AuthorizationMessageHandler. I've tried this, but it doesn't seem to work:

var loggerHandler = builder.Services.BuildServiceProvider().GetRequiredService<AuthorizationMessageHandler>()
                    .ConfigureHandler(
                            authorizedUrls: new[] { builder.Configuration.GetValue<string>("ApiBaseUrl") },
                            scopes: new[] { "dadapi" });

var levelSwitch = new LoggingLevelSwitch();
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.ControlledBy(levelSwitch)
    .Enrich.WithProperty("InstanceId", Guid.NewGuid().ToString("n"))
    .WriteTo.BrowserHttp(endpointUrl: $"{builder.Configuration.GetValue<string>("ApiBaseUrl")}/ingest"
                        , controlLevelSwitch: levelSwitch
                        , messageHandler: loggerHandler)
    .WriteTo.BrowserConsole()
    .CreateLogger();

I'm not getting any errors, but the actual http call is never getting sent to the server. I get nothing when I try to monitor it in Fiddler. If I don't pass in the MessageHandler, then the call is made. Any help would be greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants