I was using authorization fine previously with .NET 5, but suddenly after .NET 5.0.102 Context.User.Identity was not populated at all in some methods. Nothing else changed, but some places where identity was supposed to be used just didn't get the information.
This happened in controller methods as well as in Signalr hub methods. Why?
It seems .NET 5.0.102 changes the way authorization is handled and I couldn't find this from the documentation. My Signalr hub didn't have the Authorize attribute set so OnConnected etc methods didn't get any identity information. The same with the controller methods.
So every single place where you need identity needs to have Authorize attribute set!
This doesn't work in hub methods, the whole hub has to have the attribute.
I assume this is to reduce the places where the identity information is available unless you specifically ask for it, but is a breaking change that I for one did not see coming.
Note that this is documented behavior: the attribute should always be there, but for some reason it worked without before also and may cause cases where it’s left out.
Related
I've followed the tutorial from Microsoft on .NET Core claims (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/claims?view=aspnetcore-6.0#extend-or-add-custom-claims-using-iclaimstransformation)
The line if (!principal.HasClaim(claim => claim.Type == claimType)) is always true - i.e. the claim never exists in the ClaimsPrinciple after refreshing the page.
Any reason why it wouldn't stick? I have the class inherited from IClaimsTransformation and have hooked it up in program.cs
I have checked into this using .NET 6, Microsoft.Identity.Web, and Blazor Server.
The documentation says "This method might get called multiple times."
For me, the IClaimsTransformation is called each time. The might never happens.
After debugging, it seems the Microsoft.Identity.Web is providing the initial claims. The initial claims are passed to IClaimsTransformation and then my custom claims are added as a second Identity Principal which is this section of code:
principal.AddIdentity(claimsIdentity);
My custom claims are never added in duplicate and the IClaimsTransformation method fires multiple times for each page/component load.
Long story short, I think the custom claims are cleared and re-added each time IClaimsTransformation is run.
At first I was worried about performance because I was loading data from a database to generate the custom claims. So...I timed it and reading the database only required 44ms to 54ms - in other words negligible even at scale. Another benefit, is that as soon as the database is updated the claims are almost immediately reflected to the end user.
To verify yourself, you can add your custom claims using IClaimsTransformation and then setup a page to iterate through all the claims. Your custom claims should be there so long as you added the service during start-up:
services.AddTransient<IClaimsTransformation, UserClaimsTransformation>();
this is my first post, and I really have tried hard to find an answer, but am drawing a blank thus far.
My implementation of IDataContractSurrogate creates surrogates for certain 'cached' objects which I maintain (this works fine). What doesn't work is that in order for this system to operate effectively, it needs to access the service instance for some properties of the instance which it is maintaining from the interaction with its client. Also, when my implementation of IDataContractSurrogate works in its 'client mode' it needs access to the properties of the client instance in a similar way. Access to the information from the client and service instance affects how I create my surrogate types (or rather SHOULD do if I can answer this question!)
My service instancing is PerSession and concurrent.
On the server side, calls to GetDataContractType and GetDeserializedObject contain a valid OperationContext.Current from which I can of course retreive the service instance. However on the client side, none of the calls yield an OperationContext.Current. We are still in an operation as I am translating the surrogate types to the data contract types after they have been sent from the server as part of its response to the client request so I would have expected one? Maybe the entire idea of using OperationContext.Current from outside of an Operation invocation is wrong?
So, moving on, and trying to fix this problem I have examined the clientRuntime/dispatchRuntime object which is available when applying my customer behaviour, however that doesn't appear to give me any form of access to the client instance, unless I have a message reference perhaps... and then calling InstanceProvider. However I don't have the message.
Another idea I had was to use IInstanceProvider myself and then maybe build up a dictionary of all the ones which are dished out... but that's no good because I don't appear to have access to any session related piece of information from within my implementation of IDataContractSurrogate to use as a dictionary key.
I had originally implemented my own serializer but thats not what I want. I'm happy with the built in serializer, and changing the objects to special surrogates is exactly what I need to do, with the added bonus that every child property comes in for inspection.
I have also looked at applying a service behavior, but that also does not appear to yield a service instance, and also does not let me set a Surrogate implementation property.
I simply do not know how to gain access to the current session/instance from within my implementation IDataContractSurrogate. Any help would be greatly appreciated.
Many thanks,
Sean
I have solved my problem. The short answer is that I implemented IClientMessageFormatter and IDispatchMessageFormatter to accomplish what I needed. Inside SerializeReply I could always access the ServiceInstance as OperationContext.Current is valid. It was more work as I had to implement my own serialization and deserialization, but works flawlessly. The only issue remaining would be that there is no way to get the client proxy which is processing the response, but so far that is not a show stopper for me.
I have a WCF service application (actually, it uses WCF Web API preview 5) that intercepts each request and extracts several header values passed from the client. The idea is that the 'interceptor' will extract these values and setup a ClientContext object that is then globally available within the application for the duration of the request. The server is stateless, so the context is per-call.
My problem is that the application uses IoC (Unity) for dependency injection so there is no use of singleton's, etc. Any class that needs to use the context receives it via DI.
So, how do I 'dynamically' create a new context object for each request and make sure that it is used by the container for the duration of that request? I also need to be sure that it is completely thread-safe in that each request is truly using the correct instance.
UPDATE
So I realize as I look into the suggestions below that part of my problem is encapsulation. The idea is that the interface used for the context (IClientContext) contains only read-only properties so that the rest of the application code doesn't have the ability to make changes. (And in a team development environment, if the code allows it, someone will inevitably do it.)
As a result, in my message handler that intercepts the request, I can get an instance of the type implementing the interface from the container but I can't make use of it. I still want to only expose a read-only interface to all other code but need a way to set the property values. Any ideas?
I'm considering implementing two interfaces, one that provides read-only access and one that allows me to initialize the instance. Or casting the resolved object to a type that allows me to set the values. Unfortunately, this isn't fool-proof either but unless someone has a better idea, it might be the best I can do.
Read Andrew Oakley's Blog on WCF specific lifetime managers. He creates a UnityOperationContextLifetimeManager:
we came up with the idea to build a Unity lifetime manager tied to
WCF's OperationContext. That way, our container objects would live
only for the lifetime of the request...
Configure your context class with that lifetime manager and then just resolve it. It should give you an "operation singleton".
Sounds like you need a Unity LifetimeManager. See this SO question or this MSDN article.
I'm looking for some input for a challenge that I'm currently facing.
I have built a custom WIF STS which I use to identify users who want to call some WCF services that my system offers. The WCF services use a custom authorization manager that determines whether or not the caller has the required claims to invoke a given service.
Now, I'm building a WPF app. on top of those WCF services. I'm using the MVVM pattern, such that the View Model invokes the protected WCF services (which implement the Model). The challenge that I'm facing is that I do not know whether or not the current user can succesfully invoke the web service methods without actually invoking them. Basically, what I want to achieve is to enable/disable certain parts of the UI based on the ability to succesfully invoke a method.
The best solution that I have come up with thus far is to create a service, which based on the same business logic as the custom authorization policy manager will be able to determine whether or not a user can invoke a given method. Now, the method would have to passed to this service as a string, or actually two strings, ServiceAddress and Method (Action), and based on that input, the service would be able to determine if the current user has the required claims to access the method. Obviously, for this to work, this service would itself have to require a issued token from the same STS, and with the same claims, in order to do its job.
Have any of you done something similar in the past, or do you have any good ideas on how to do this?
Thanks in advance,
Klaus
This depends a bit on what claims you're requiring in your services.
If your services require the same set of claims, I would recommend making a service that does nothing but checks the claims, and call that in advance. This would let you "pre-authorize" the user, in turn enabling/disabling the appropriate portions of the UI. When it comes time to call your actual services, the user can just call them at will, and you've already checked that it's safe.
If the services all require different sets of claims, and there is no easy way to verify that they will work in advance, I would just let the user call them, and handle this via normal exception handling. This is going to make life a bit trickier, though, since you'll have to let the user try (and fail) then disable.
Otherwise, you can do something like what you suggested - put in some form of catalog you can query for a specific user. In addition to just passing a address/method, it might be nicer to allow you to just pass an address, and retrieve the entire set of allowed (or disallowed, whichever is smaller) methods. This way you could reduce the round trips just for authentication.
An approach that I have taken is a class that does the inspection of a ClaimSet to guard the methods behind the service. I use attributes to decorate the methods with type, resource and right property values. Then the inspection class has a Demand method that throws an exception if the caller's ClaimSet does not contain a Claim with those property values. So before any method code executes, the claim inspection demand is called first. If the method is still executing after the demand, then the caller is good. There is also a bool function in the inspection class to answer the same question (does the caller have the appropriate claims) without throwing an exception.
I then package the inspection class so that it is deployed with clients and, as long as the client can also get the caller's ClaimSet (which I provide via a GetClaimSet method on the service) then it has everything it needs to make the same evaluations that the domain model is doing. I then use the bool method of the claim inspection class in the CanExecute method of ICommand properties in my view models to enable/disable controls and basically keep the user from getting authorization exceptions by not letting them do things that they don't have the claims for.
As far as how the client knows what claims are required for what methods, I guess I leave that up to the client developer to just know. In general on my projects this isn't a big problem because the methods have been very classic crud. So if the method is to add an Apple, then the claim required is intuitively going to be Type = Apple, Right = Add.
Not sure if this helps your situation but it has worked pretty well on some projects I have done.
Ok, Im really going to show my stupidity regarding the ASP.NET security model here but here goes.
I have a WCF web service and I have managed to hack my way around to having it pipe through my custom membership provider.
My membership provider overrides "ValidateUser" in which I attempt to load a user object with data from our SQL server instance. All good so far, I retrieve the creds, load the users object and return true if I don't hit any bumps in the road.
At this point, I would usually stuff the user object (or id) into session or actually just some state bag that's accessible for the lifetime of the request. The problem that I am hitting is that HttpContext is null at this point, even though Im using ASP compatability attributes.
What other options do I have at hand?
Cheers, Chris.
EDIT:
Just to clarify what I want to do. I want to pass user credentials to be authenticated on the server, and once this has happened I would like to keep the the details of the authenticated user somewhere that I can access for the lifetime of the service request only. This would be the equiv of Http.Current.Items?
Is there any object that is instantiated per-request that I can access globally via a static property (i.e. in a similar way to HttpContext.Current)? I assumed that OperationContext was the this, but this is also null?
Can this really be such an uncommon problem? Send creds > retrieve user > stuff user somewhere for access throughout processing the request. Seems pretty common to me, what am I missing?
Cheers, Chris.
Basically, with WCF, the preferred best practice solution is to use per-call activation, e.g. each new request / call gets a new instance of the service class, and all the necessary steps like authentication and authorization are done for each request.
This may sound inefficient, but web apps, and in particular web services, ought to be totally stateless whenever possible. Putting stuff in a "state bag" just calls for problems further down the road - how do you know when to invalidate that cached copy of the credentials? What if the user exists your app but the cookie stays on his machine?
All in all, I would strongly suggest trying to get used to the idea of doing these step each and every time. Yes, it costs a little bit of processing time - but on the other hand, you can save yourself from a lot of grief in terms of state management in an inherently stateless environment - always a kludge, no matter how you look at it....
If you still insist on that kludge, you can turn on an ASP.NET "compabitility" mode for WCF which should give you access to HttpContext - but again: I would strongly recommend against it. The first and most obvious limitation is that this ASP.NET compatibility mode of course only works when hosting your WCF service in IIS - which I would again rather not do in production code myself.
To turn on the ASP.NET compatibility mode, use this setting in web.config:
<system.serviceModel>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
and you need to decorate your service implementation (the class implementing the service contract) with a corresponding attribute:
[AspNetCompatibilityRequirements(RequirementsMode=
AspNetCompatibilityRequirementsMode.Allowed)]
class YourService : IYourService
The AspNetCompatibilityRequirementsMode can be NotAllowed, Allowed or Required.
For more information and a more thorough explanation, see Wenlong Dong's blog post on ASP.NET Compatibility Mode