I detected a problem in the RequestFilter
execution order.
The ValidationFeature
in ServiceStack is a Plugin that just registers a Global Request Filter. The Order of Operations points out that Global Request Filters are executed after Filter Attributes with a Priority <0 and before Filter Attributes with a Priority >=0
My BasicAuth
filter has -100 priority, and in fact everything goes well if the Service
is annotated at class level, but it fails when the annotation is at method level, with the authentication filter being executed after.
I am using 3.9.70 Is there any quick fix for this? Thanks
When you add the annotation at method level then you are creating an
Action Request Filter
(because you are adding the annotation to an action method) which in the Order of Operations is operation 8, after the other filters have run.The best workaround I can suggest is to reconsider your service structure. I imagine you are having these difficulties because you are adding unauthenticated api methods alongside your secure api methods, and thus are using method level attributes to control authentication. So you are presumably doing something like this Your classes and attributes will be different, this is just exemplar:
I would do this differently, and separate your insecure and secure methods into 2 services. So I use this:
Solution - Deferred Validation:
You can solve your execution order problem by creating your own custom validation feature, which will allow you to defer the validation process. I have created a fully functional self hosted ServiceStack v3 application that demonstrates this.
Full source code here.
Essentially instead of adding the standard
ValidationFeature
plugin we implement a slightly modified version:Configure to use our plugin:
Then we need to create our custom attribute. Your attribute will be different of course. The key thing you need to do is call
ValidationFilters.RequestFilter(req, res, requestDto);
if you are satisfied the user has the required role and meets your conditions.For this to work we need to apply our custom attribute on the DTO route not the action method. So this will be slightly different to how you are doing it now, but should still be flexible.
Then your service would look something like this:
So when we call the route
/EinsteinsBirthday
which does not have aMyRole
attribute the validation will be called normally, as if using the standardValidationFeature
.If we call the route
/HaveChristmas?role=Santa
then our validation plugin will determine that the DTO has our attribute and not run. Then our attribute filter triggers and it will trigger the validation to run. Thus the order is correct.