Access Current OwinContext - c#

I’m working on an OWIN hosted ASP.Net WebApi2 Microservice. We are using Autofac as Dependency Injector.
When my service gets called I can get information about the user by accessing owinContext.Request.User.Identity. My problem is when I have to make a call to another service and pass the user information along. I have to create an authorization token that includes the user information and set that token to the RequestMessage.
I would like to write a DelegatingHandler that I can put in the “HttpClient-MessageHandler-Pipline”. But inside DelegatingHandler.SendAsync() I would need to have access to the current OwinContext.
I thought about different approaches. But I really hope there is something easier and less error prone (or maybe a hint how I could make one of this approach feasible):
With Autofac I can’t easily solve the Captive Dependency Problem: The HttpClient and therefore the DelegatingHandler are registered as SingleInstance. But the OwinContext is registered on a LifeTimeScope. So I can’t just inject the OwinContext to the constructor of the DelegatingHandler.
I could write an Owin-Middleware that sets the OwinContext on a static System.Threading.AsyncLocal variable. Inside the DelegatingHandler I could access that static variable. But mutable global variables just feels really wrong to me.
I don’t write a DelegatingHandler at all. Inside my ServiceRepository (that can also be registered on the LifeTimeScope) I would have to construct all the RequestMessages by hand. Then it would be easy to set the AuthorizationToken onto the RequestMessage. But not using the convenience methods like e.g. httpClient.PostAsJsonAsync() brings a lot of work with it.

public class MyHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
HttpResponseMessage response = task.Result;
IOwinContext owinContext = request.GetOwinContext();
// do something with the response and owinContext
return response;
},
cancellationToken);
}
}

Related

ILogger and DependencyInjection Architecture in ASP.NET Core

My team is pretty big on DependencyInjection. Personally I'm a bit too far out of the loop lately to really judge the correct usage of this. But I do see more and more code like this:
public AuthenticationApi(ILogger<AuthenticationApi> logger,
HttpClient httpClient,
IJsonConverter jsonConverter,
IDtoConverter dtoConverter) : base(logger, httpClient, jsonConverter)
{
_dtoConverter = dtoConverter;
}
And then this multiplies across the code, where half of our code is just calling constructors with endless
DependencyInjection related stuff. My team told me, that's the way of .NET Core. And yes, answers like this confirm it:
ILogger and DependencyInjection in ASP.NET Core 2+
And discussions like that would be more along my gut feeling that things like logging, etc. should just be transparent and not handled in endless DependencyInjection constructor chains:
https://softwareengineering.stackexchange.com/questions/371722/criticism-and-disadvantages-of-dependency-injection
In another place (unfortunately I can't find the article anymore), I read that this constructor issues are mainly a result of badly implemented Service Factories.
Thoughts on the topic are appreciated.
Based on the discussion below, this is the baseclass and uses both the Logger and the HttpClient:
internal class ApiBase
{
private readonly ILogger _logger;
private readonly IJsonConverter _jsonConverter;
private readonly HttpClient _httpClient;
public ApiBase(ILogger logger, HttpClient httpClient, IJsonConverter jsonConverter)
{
_logger = logger;
_jsonConverter = jsonConverter;
_httpClient = httpClient;
}
protected async Task<T> GetAsync<T>(string path, HttpContent content = null)
{
_logger.LogDebug($"Sending GET request to {path}");
using (var request = new HttpRequestMessage(HttpMethod.Get, path))
{
request.Content = content;
using (var response = await _httpClient.SendAsync(request).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
_logger.LogDebug($"GET request to {path} was successful.");
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var deserializeResponseContent = _jsonConverter.Deserialize<T>(responseContent);
return deserializeResponseContent;
}
var message = GetErrorMessage("GET", path, response);
_logger.LogError(message);
throw new HttpRequestException(message);
}
}
}
And then this multiplies across the code, where half of our code is just calling constructors with endless DependencyInjection related stuff. My team told me, that's the way of .NET Core.
Yes and no. Constructor injection of dependencies is a standard method in .NET Core to organize your dependencies. And it works great.
What is non-standard is your base class and the fact that you have those constructor chains where half your parameters aren't actually needed, but just go into the base class constructor. I will bet that this base class does not actually do anything worthwhile.
Remove the base class. See what you still need for every controller. Only inject that. These base classes and their own constructors are a great way to obfuscate what the actual dependencies are. Because now suddenly every class needs an IJsonConverter, must be pretty important. But you will have a hard time figuring out who actually makes use of the base class functionality that uses it. So of your 20 classes derived of the base, who really needs it, and who only requires it to make the compiler happy?
My advice is to remove the base class. Inject into each controller what they need, not more and not less. So you can actually see the dependencies. If you have common functionality in that base class, it can probably be a static method somewhere that gets those fields as parameters. Or maybe it can be a service of it's own that is injected where needed. But only where needed.

What is the proper way of getting the HTTP request method in an AuthorizationHandler<T>?

Simplified version of what I'm trying to do: I want to write an authorization policy that will block requests that aren't GET if a flag is set in the database. I registered my policy, the handler code runs fine for my controller, but I'm not sure what the best way of getting the HTTP method type is.
Controller looks like this:
[Authorize(Policy = "Test")]
public class MyController : ControllerBase
{
// ...
}
My handler looks like this:
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext ctx, MyRequirement req)
{
// Fetch some flag from db
if (!flag)
{
ctx.Succeed(req);
return;
}
var method = GetRequestMethodFromCtx(ctx.Resource);
if (method == HttpMethods.Get)
{
ctx.Succeed(req);
}
else
{
ctx.Fail();
}
}
I noticed that for a single request my handler gets called multiple times and that ctx.Resource is not always the same type. First time it is a RouteEndpoint, after which it is an AuthorizationFilterContextSealed.
Should I just extract the HTTP method from the RouteEndpoint and ignore the second call? Also, why are there multiple calls to the handler?
In order to access to HttpContext object you can use the IHttpContextAccessor service.
You can simply require it as a dependency of your authorization handler class and the ASP.NET core dependency injection will provide the service for you.
In order to register it with the dependency injection you need to call services.AddHttpContextAccessor() in the ConfigureServices method of your Startup class.
From the HttpContext you will have access to the Request and then to the Method property (see here).
Refer to the official documentation for the details.
I don't know exactly your requirements, but in order to prevent an action method being called with a specific HTTP verb there is a much simpler way. You just need to use the built in routing attributes, you can find more information here.

Autofac Injecting ClaimsPrincipal in Blazor Application

I'm facing issues with registering a service with Autofac in a Blazor application. Deep in a dependency I have a UserService which needs access to the current ClaimsPrincipal. I've wrapped that with IPrincipalProvider to avoid registering the ClaimsPrincipal directly.
My issue stems from the fact that in Core the current principal isn't set on program start and the way to get the principal is to register AuthenticationStateProvider which is set by ASP.NET Core. I've gone with ServerAuthenticationStateProvider:
builder.RegisterType<ServerAuthenticationStateProvider>()
.As<AuthenticationStateProvider>().InstancePerLifetimeScope();
This allows access to the logged on user and I can display their name on the website easily.
So to get this principal registered the next entry must use a delegate in order to get the ClaimsPrincipal from the state provider using GetAuthenticationStateAsync(). Being a Task based method I figured I would just mark the lambda with async:
builder.Register(
async c =>
{
var authStateProvider = c.Resolve<AuthenticationStateProvider>();
var authState = await authStateProvider.GetAuthenticationStateAsync()
.ConfigureAwait(false);
return new PrincipalProvider(authState.User);
}).As<IPrincipalProvider>();
but I get the following error:
System.ArgumentException: 'The type 'System.Threading.Tasks.Task`1[Perigee.Framework.Services.Security.PrincipalProvider]' is not assignable to service 'Perigee.Framework.Base.Services.IPrincipalProvider'.'
Given I'm newing up the PrincipalProvider explicitly I'm not really sure why it thinks it's Task. I have to await the authStateProvider.GetAuthenticationStateAsync() call so definitely need the async modifier. If I remove the async and only return new PrincipalProvider(new ClaimsPrincipal()); then the registration works and the lambda resolves at runtime (I've checked with a breakpoint in the lambda) so I know the form of what I'm doing is correct.
Can someone please point out what I'm missing in relation to making the instantiation of the PrincipalProvider not be treated as a Task?
UPDATE:
Well I found a way of doing this using an async task within the Registration body:
builder.Register(
c =>
{
var authStateProvider = c.Resolve<AuthenticationStateProvider>();
var authStateTask = Task.Run(async () => await authStateProvider
.GetAuthenticationStateAsync().ConfigureAwait(false));
var authState = authStateTask.GetAwaiter().GetResult();
return new PrincipalProvider(authState.User);
}).As<IPrincipalProvider>();
Problem is:
System.InvalidOperationException
HResult=0x80131509
Message=GetAuthenticationStateAsync was called before SetAuthenticationState.
Source=Microsoft.AspNetCore.Components.Server
I'm confused about why this wouldn't be available. The site is building the injectable service and passed to the [Inject] property on the page being loaded.
Anyone know how to make this work? I'd would like to put AuthenticationStateProvider as my injected service which is deep in my other dependency, but that library isn't related to ASP.NET at all. It's a CQRS based library for doing all sorts of things, mainly used for Entity Framework queries and commands so putting a dependency to an ASP.NET type makes little sense.
UPDATE AGAIN:
Thinking further registering a different implementation of IPrincipalProvider that received AuthenticationStateProvider on creation seems to be a working solution:
public class DeferredPrincipalProvider : IPrincipalProvider
{
private readonly AuthenticationStateProvider _authenticationStateProvider;
public DeferredPrincipalProvider(
AuthenticationStateProvider authenticationStateProvider)
{
_authenticationStateProvider = authenticationStateProvider;
}
public ClaimsPrincipal ClaimsPrincipal
{
get
{
var authStateTask = Task.Run(async () => await _authenticationStateProvider
.GetAuthenticationStateAsync()
.ConfigureAwait(false));
var authState = authStateTask.GetAwaiter().GetResult();
return authState.User;
}
}
}
Which is wired up with:
builder.RegisterType<ServerAuthenticationStateProvider>().As<AuthenticationStateProvider>()
.InstancePerLifetimeScope();
builder.RegisterType<DeferredPrincipalProvider>().As<IPrincipalProvider>();
I'm not too happy with the Task within the getter, so will switch it to an async method. GetResult() isn't intended to be called from non .NET Framework code anyway according to MS doco.

Migrating from manually managed HttpClient (with separate TokenUri) to IHttpClientFactory

I have got an web application that lacks to free memory.
I suspect HttpClient to be one of the issues, because the object count of HttpClient is increasing over time.
Therefore I want to migrate to the managed IHttpClientFactory, but now I'm stuck with how to best implement the call to the token service (I thought about using the typed client variant).
Right now it's implemented this way:
var myClient = new MyClient(credentials, baseUri, tokenUri, timeout);
Inside of MyClient HttpClient(1) takes care of calling the token service (credentials, tokenUri), storing the expiry date and returning the bearer token to HttpClient(2) that calls the endpoint (baseUri, timeout).
If myClient now tries to fetch some data, it checks if the token needs to be refreshed, if not it fetches the data.
How would I do this with IHttpClientFactory? Do I still need to handle HttpClient(1) myself (expiry date) or will the factory somehow detect if it needs to refresh the token or not?
I at least understood, that the factory decides if a connection stays open or not.
It sounds like you're on the right track with the transition to HttpClientFactory, and particularly a typed HttpClient.
Under the hood, HttpClientFactory's default implementation manages the pooling and disposal of the underlying primary message handler, which means that the actual HttpClient sitting on top of it can start being generated and disposed in a scoped fashion rather than trying to manage some global, long-running instance of it or creating and tearing down one-off instances, which is well described in Microsoft's own documentation: Use IHttpClientFactory to implement resilient HTTP requests
In cases like yours where the HttpClient was potentially long-lived, it may have made sense for the client itself to manage state within its instance (such as the token), but you end up needing to take a different path now that the client can (and should) be disposed of more frequently.
Do I still need to handle HttpClient(1) myself (expiry date) or will the factory somehow detect if it needs to refresh the token or not?
Yes you still need to handle it, but the HttpClientFactory pattern gives you some tools to help manage it. Since you're inherently leaning into dependency injection with the use of HttpClientFactory, there's a couple different paths you might go.
At the most basic would be just to add some sort of singleton token provider that manages the tokens for you and can be injected into the typed client by the DI container:
public interface ITokenProvider
{
string GetToken(string key);
void StoreToken(string key, string token);
}
// Incredibly basic example, not thread safe, etc...
public class InMemoryTokenProvider : ITokenProvider
{
private readonly Dictionary<string, string> _tokenList = new Dictionary<string, string>();
public string GetToken(string key)
{
return _tokenList.GetValueOrDefault(key);
}
public void StoreToken(string key, string token)
{
_tokenList.Remove(key); // upsert, you get the point...
_tokenList.Add(key, token);
}
}
public class TypedClient
{
private readonly HttpClient _client;
private readonly ITokenProvider _tokenProvider;
public TypedClient(HttpClient client, ITokenProvider tokenProvider)
{
_client = client;
_tokenProvider = tokenProvider;
}
public async Task DoYourThing()
{
var token = _tokenProvider.GetToken("token_A");
// ... if it failed, then UpdateTheAuth()
}
private async Task UpdateTheAuth()
{
var result = await _client.GetAsync("the auth process");
string token = "whatever";
// ...
_tokenProvider.StoreToken("token_A", token);
}
}
When you do your service registration at the start and register the token provider as a singleton, all your state (such as the token) is no longer part of the client itself, so your client can now be disposed and injected wherever. That provider could also be written off to a cache or a database, too.
This can still be a little clunky because its still putting all the logic for calling, failing, updating auth, retrying, etc. within your typed client logic -- it might be good enough if that covers what you need, or you may want something more robust. HttpClientFactory makes it easy to add a delegating handler pipeline as well as policies for resiliency with Polly, such as retry:
services.AddTransient<ExampleDelegatingHandler>();
services.AddHttpClient<IMyHttpClient, MyHttpClient>()
.AddHttpMessageHandler<TokenApplicationHandler>()
.AddPolicyHandler(GetRetryPolicy()); // see Microsoft link
The delegating handler pipeline attaches to your typed client and runs like middleware for every request and response (and can modify them in flight), so you could even move some of this token management off into a delegating handler instead:
public class TokenApplicationHandler : DelegatingHandler
{
private readonly ITokenProvider _tokenProvider;
private readonly IAuthRenewerClient _authRenewer;
public TokenApplicationHandler(ITokenProvider tokenProvider, IAuthRenewerClient authRenewer)
{
_tokenProvider = tokenProvider;
_authRenewer = authRenewer;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// All just demo level, take the implementation with a grain of salt...
string token = _tokenProvider.GetToken("token_A");
request.Headers.Add("x-token-header", token);
var response = await base.SendAsync(request, cancellationToken);
if (!response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.Unauthorized)
{
string newToken = _authRenewer.RefreshAuth();
_tokenProvider.StoreToken("token_A", newToken);
}
return response;
}
}
Paired with a retry policy, now any time a request goes out and comes back with an Unauthorized response, your delegating handler can handle the renewal and then the request gets resent the new token, and your typed HttpClient doesn't need to be any the wiser (or even necessarily deal with auth at all).
Key takeaways, make sure as you transition to this pattern that you're disposing of the clients you're creating when you're done with whatever scope they're in so HttpClientFactory can do its background magic.

Inject IPrincipal with SignalR

I am trying to inject IPrincipal into my SignalR hub constructors.
I already saw and tried the solution from "Selective IPrincipal Injection via StructureMap with SignalR", but unfortunately that doesn't seem to work anymore for SignalR 2.x.
In my debugging, I've discovered that sometimes, my hub constructor is called with my OWIN middleware in the stack. When that is the case, Thread.CurrentPrincipal is the correct value. Additionally (and surprisingly), HttpContext.Current is also not-null. I was under the impression this was always null in SignalR, and I'm not attempting to use it, but I'm just observing. It seems like these calls that do work come from the pipeline in the call stack.
Other times, calls seem to come from the thread pool. In those instances, Thread.CurrentPrincipal is a GenericPrincipal, HttpContext.Current is null (again just observing), and I cannot seem to get at the principal statically. However, inside the hub, the this.Context.User property does have the right principal.
How else can I get the principal statically so that I can inject it into the hub constructor?
It is expected that HttpContext.Current and Thread.CurrentPrincipal will sometimes be set when SignalR Hubs get activated, but not always. This is because the activating thread often runs with ASP.NET's SynchronizationContext. There are situations when this isn't the case, such as when a Hub is activated in order to handle a WebSocket message or an unclean OnDisconnected event. Long story short, sometimes these statics happen to be there, but you cannot rely on it.
I don't know of any way to statically get the IPrincipal reliably. What's wrong with using Context.User inside your Hub?
If I understood correctly what you're trying to do... You should build your own Authorize attribute, that will put the custom principal into a special Owin var, then it will be accessible in Context.User inside a hub.
public class MyAuthorizeAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
{
//put our custom user-principal into a magic "server.User" Owin variable
request.Environment["server.User"] = new MyCustomPrincipal(); //<!-THIS!
return base.AuthorizeHubConnection(hubDescriptor, request);
}
}
And then apply this attribute to your Hub.
If you want more info on this, I blogged about this here with more code samples
I was trying to solve the same problem and I found solution to set the identity of the user.
My application is saml protected and client application sends "SAML" token as part of header. We have written Asp.net module to verify the token and prepare identity of the user and add value to the response Headers.
I have created OwinStartup class and I have added my own request processor by using below code.
I have tested this piece of code for Longpolling and working fine. I am not sure how it works in "WebScoket".
public void Configuration(IAppBuilder app)
{
// Any connection or hub wire up and configuration should go here
try
{
app.Use(SetMyPrincipalObject);
}
}
private Task SetMyPrincipalObject(IOwinContext arg1, Func<Task> arg2)
{
//var p = "Process response";//Process Response Header here and //create identity
//arg1.Request.User = p;
//return arg2.Invoke();
}

Categories

Resources