There are an option in ServiceStack to add routes dynamically, using IAppHost.Routes.Add. This is quite handy as it allows reusable services to be packed in a form of plugin and attached to actual applications.
To illustrate, here's an excerpt of application host configuration that enables a plugin and attaches routes:
class AppHost: AppHostHttpListenerBase {
public override void Configure(Container container) {
// other stuff
Plugins.Add(new MyReusablePlugin());
Routes.Add(typeof(string), "/stuff", "GET");
Routes.Add(typeof(string), "/other-stuff", "POST");
}
}
The problem is, I can't find a way to specify that authentication is required for those dynamically added routes. As of ServiceStack 4.0.15 there are no overload to Routes.Add that allow specifying that those routes require authentication. Is it possible (maybe in newer versions)?
Ideally, such a mechanism should support specifying roles/permissions, just like RequiredRoleAttribue or RequiresAnyRoleAttribute.
One more thing: I'm aware of Global request filters and it looks like they are a bit too global to be a valid solution here, but I might be wrong. If it's possible to achieve the same result (including ability to specify required roles/permissions) using request filters I would be glad to accept an example of such apporach as an answer.
You can do this using the AddAttributes extension method provided on Type:
typeof(YourType).AddAttributes(new RequiredRoleAttribute("Admin"));
So you would need to do this in addition to the Routes.Add method.
Related
In Quarkus (resteasy reactive), is there a way to get hold of the "ResourceInfo" in an HTTP Authentication Mechanism?
What I'm trying to do is read an annotation that is defined on the resource class or method, in order to choose an authentication mechanism based on it.
Injecting the ResourceInfo directly in the mechanism class does not work (and also, it is application scoped and not request scoped, so not sure it could work). I also couldn't find the info I need in the RoutingContext parameter.
I have also tried adding a ContainerRequestFilter, in which injecting the ResourceInfo with #Context works well, but I think perhaps the filters are called after the httpAuthenticationMechanism.authenticate(), because it's not called in my test when the endpoint requires authentication.
Is there another way to do this?
----> To clarify with code what I would like to do:
have different JAX-RS resources with a custom #Authorization annotations with different "api names" like this:
#Path("/jwttest")
#ApplicationScoped
#Authorization("jwttest")
public class JWTTestController {
...
}
#Path("/oidctest")
#ApplicationScoped
#Authorization("myoidc")
public class OIDCTestController {
...
}
and then different configs like this:
myframework.auth.jwttest.type=jwt
myframework.auth.jwttest.issuer=123
myframework.auth.jwttest.audience=456
myframework.auth.myoidc.type=oidc
myframework.auth.myoidc.auth-server-url=myurl
And in the HttpAuthenticationMechanism, find the value of #Authorization, and based on it, call another provider like suggested in https://quarkus.io/guides/security-customization#dealing-with-more-than-one-httpauthenticationmechanism with the right api name so that it can load the config.
I'm currently making a library that interacts with a particular API that requires an oAuth OIDC connection/token and I'd like to make something that makes that particular part easier for users of this library so they don't need all this custom code.
What is this currently called and is there an example of code?
I ask because from trying to get this work, the documentation is ALL OVER THE PLACE. It looks like this particular process has undergone significant changes multiple times as things went on from before netcore to netcore2 and now netcore31.
Both AddAuthentication and AddOpenIdConnect are extension methods.
An extension method allows you to "add" methods to a type without having to modify the type directly - the methods aren't actually added to the type, but we can call them as if they had been. This is useful in situations where you'd like to extend the behaviour of a class created by a third party but don't have access to the source code.
As for what the particular pattern in question is, whilst there is no canonical name, it's merely a way of encapsulating the configuration of services and dependencies for your application.
AddAuthentication is an extension method of IServiceCollection, which is services type. AddAuthentication has a return type of AuthenticationBuilder, and AddOpenIdConnect is an extension method for AuthenticationBuilder. This is the implementation of AddOpenIdConnect, but as you're looking to encapsulate the configuration, you could probably do something like this:
public static class OpenIdConnectExtensions
{
public static AuthenticationBuilder ConfigureOpendIdConnect(
this AuthenticationBuilder builder)
{
return builder.AddOpenIdConnect(options =>
{
options.SignInScheme = IdentityConstants.ExternalScheme;
// Do whatever else you need.
});
}
}
And call it as follows:
services
.AddAuthentication()
.ConfigureOpendIdConnect()
Middleware, on the other hand, is code that executes as part of a pipeline in order to process requests and responses. The middleware sits in the middle of receiving requests and sending responses, hence the name. This allows you do things such as always adding certain headers to responses without that logic being split across your application. As you correctly mentioned, you see these being applied via calls such as app.UseXyz().
Looking on different libraries and even Microsoft code I've noticed two different ways of configuring options in code:
in ConfigureServices it can be done when registering DependencyInjection:
services.AddMvc(options => { });
or in Configure
app.UseStaticFiles(
new StaticFileOptions
{
ServeUnknownFileTypes = true
});
I tried to find out, which way use for which purpose and still don't know, assuming that creating your own middleware and registering both DI and usage.
Interesting issue you have found.
Looking into the source code i have found the following:
All the middleware registrations are an overload of this UseMiddleware function, which is an overload of IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);.
In these overloads you can specify hard your own parameters for the middle-ware. Say you have a few strings in the constructor, the DI container will not be able to resolve this.
If the parameters aren't set though, it does fallback to the IServiceProvider to resolve the specific type. see extension class: Microsoft.Extensions.Internal.ActivatorUtilities (inside: Microsoft.AspNetCore.Http.Abstractions.dll)
Tips
As for best practice think about the following (my opinion though):
Try to avoid using simple types in constructor but use an Options class.
for IOptions use services.Configure<>() as here you can specify options from a ConfigSection => appsettings.
As for Services: be aware that middleware is a singleton! so adding a transient Service, will only be resolved once for this middleware!
I think best practise is to: Register Middleware AND its dependencies as singletons in IOC on startup. then resolve it yourself and add it yourself with the method App.Use([yourDelegate]).
The advantage of this method is it is easilier understandable than use the hidden microsoft code + Microsoft recently published an upgrade to the DI container to check if the scopes of your registrations match properly (and warn you if not).
This tool basically does: it checks if a dependency of a service has a smaller scope then the service itself: say service is scope: Singleton and the dependency is scope Transient. this means that if Singleton is resolved Transient is also resolved for this singleton and thus not resolved again on next usage of this singleton. (so its a hidden singleton usage).
I'm moving a Web Api 2 project to MVC 6, since Microsoft is merging the two APIs in ASP.NET 5. In my WebApi project I had a custom Attribute Filter class that would authenticate, authorize and prevent transaction replays using a combination of public key, private key and HMAC authentication (basically, doing this with some tweaks to fit into my project).
Now in MVC6, as far as I understand I must stop using anything in the Microsoft.Web.Http namespace and instead use Microsoft.AspNet.Mvc. So I have done that, but the Microsoft.AspNet.Mvc.Filters doesn't seem to have any equivalent of Web Api 2's IAuthenticationFilter.
This is a problem for me because my customer AuthenticationFilter implemented all of IAuthenticationFilter, with all the logic in there. More importantly, it was using the Context to temporarily store the public key of the account, so my controller could access it to load up the account in turn.
So my question is, what is the proper way to filter requests in MVC6, using an Authentication Filter-like class to intercept the requests and return the appropriate status codes? I can't find any article that goes specifically in these details (they all tend to cover MVC5).
I know it's an older question, but hopefully someone (maybe even yourself) might find value in the answer.
MVC6 does in fact have an alternative. You have an
public abstract class AuthorizationFilterAttribute :
Attribute, IAsyncAuthorizationFilter, IAuthorizationFilter, IOrderedFilter
which basically tells you, that you can create your custom class, derive it from this (namespace of all of these interfaces, btw, is Microsoft.AspNet.Mvc.Filters and that should be it. You can either decorate the action with it, or you can do this in Startup.cs, to apply to all actions:
public void ConfigureServices(IServiceCollection services)
{
// Add MVC services to the services container.
services.AddMvc(options =>
{
// add an instance of the filter, like we used to do it
options.Filters.Add(new MySpecialFilter());
});
services.AddTransient<LogFilter>();
}
If you want to use a bit more logic in the filter (e.g. my LogFilter above) which is instantiated through DI, you need to use either Service Filters or Type Filters.
You can now decorate the actions with [ServiceFilter(typeof(LogFilter))] or use o.Filters.Add(new ServiceFilterAttribute(typeof(LogFilter))); in the Startup.cs file. But keep in mind, to do this you need to register the type with the DI container, like I did above with the .AddTransient<>() call.
IAuthenticationFilter is no more and IAuthorizationFilter simply does not replace it in MVC 6
Reason: authentication is NOT EQUAL to authorization.
Therefore IMO the authentication filter should stay available!
I have developed a web application based on Restlet API. As I am adding more features over time, I need sometimes to reuse similar group of REST API under different endpoints, which provides slightly different context of execution (like switching different instances of databases with same schema). I like to refactor my code to make the API reusable and reuse them at different endpoints. My initial thinking was to design an Application for each reusable API and attach them on the router:
router.attach("/context1",APIApplication.class)
router.attach("/foo/context2",APIApplication.class)
The API should be agnostic of configuration of the REST API. What is the best way to pass context information (for example the instance of database) to the Application API? Is this approach viable and correct? What are the best practices to reuse REST API in Restlet? Some code samples would be appreciated to illustrate your answer.
Thanks for your help.
I have see this basic set-up running using a Component as the top level object, attaching the sub applications to the VirtualHost rather than a router, as per this skeleton sample.
public class Component extends org.restlet.Component
{
public Component() throws Exception
{
super();
// Client protocols
getClients().add(Protocol.HTTP);
// Database connection
final DataSource dataSource = InitialContext.doLookup("java:ds");
final Configuration configuration = new Configuration(dataSource);
final VirtualHost host = getDefaultHost();
// Portal modules
host.attach("/path1", new FirstApplication());
host.attach("/path2", new SecondApplication(configuration));
host.attach("/path3", new ThirdApplication());
host.attachDefault(new DefaultApplication(configuration));
}
}
We used a custom Configuration object basically a pojo to pass any common config information where required, and used this to construct the Applications, we used separate 'default' Contexts for each Application.
This was coded originally against restlet 1.1.x and has been upgraded to 2.1.x via 2.0.x, and although it works and is reasonably neat there may possibly be an even better way to do it in either versions 2.1.x or 2.2.x.