-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Add AuthorizationPolicyCache #43227
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
Comments
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
API review questions?
|
Also, do we think this a worthy use of publicly mutable metadata? @JamesNK what do you think? |
I think this is abusing what the endpoint metadata collection is intended for. |
This is purely a brainchild of @davidfowl and @DamianEdwards 😆 |
YARP makes endpoints and adds metadata to them: |
What about? namespace Microsoft.AspNetCore.Authorization;
+ public static class AuthorizationCacheEndpointConventionBuilderExtensions
+ {
+ public static TBuilder WithAuthorizationCache<TBuilder>(this TBuilder builder) where TBuilder : IEndpointConventionBuilder;
+ } The "correct" namespace is Microsoft.AspNetCore.Builder, but I want to hide this a little, because I expect most people will get this by calling some overload of |
There's one alternative to making it mutable but its a little crazy (good crazy). We do this optimization after we get #43225. We do this caching using Finally. We'd resolve the service in there and cache the "final" metadata if it's the default implementation (we can resolve the policy then and cache this immutable version of the metadata). |
I love the |
Does it need to? This is purely an optimization that happens in the 99% case:
Other frameworks will work and can call the For MVC and pages, we can just always call this internally, I assume the call will be smart enough to find the metadata and do the needful, otherwise it'll noop. |
Exactly! Apparently YARP could use I'm not sure it's quite the 99% case. I think as more people use route handlers, more people are going to use them with attributes. Remember not all route handlers are lambdas. I'm kinda leaning towards putting it in |
We can make that work as well (implicitly) 😄
Sounds good. |
YARP or any other framework would only need to add the The problem with just a method on Also be aware that the Overall isn't this leaking of implementation details!? If I'm creating my endpoints by directly creating my own Could we just have a non-readonly collection on |
Mutable shared state leads to bugs. We should be shifting as much as we can to startup for situations like this. |
I would argue that frameworks that are just using
It is annoying that you need to know about the cache in some situations. Of course, everything will continue to work as it does today without it, but I see your point. I was tempted to say we should add an internal property to the AuthorizeAttribute itself, but that wouldn't work for custom attributes implementing
It is tempting, but I think I agree with @davidfowl that we should at least hide mutable state on the namespace Microsoft.AspNetCore.Builder;
public static class AuthorizationEndpointConventionBuilderExtensions
{
+ public static TBuilder WithAuthorizationCache<TBuilder>(this TBuilder builder) where TBuilder : IEndpointConventionBuilder;
} |
Looks good to me, I like it |
API Approved! |
Re: Default Policy provider. We have our own policy provider that turns various policy names into corresponding policies. For example we have an attribute that takes a permissions enum and a resource type which generates an This is very useful in both our MVC application, but especially in our YARP gateway where policy names are pulled from external configuration sources rather than attributes, and are usually unique to each proxied endpoint. Defining the individual policies ahead of time in-app just wouldn't be feasible, hence our custom provider which can turn recognized patterns into policies. We aren't injecting services and/or doing anything more than turning a name (and possibly the current I realize that by rolling our own we are in an advanced, not-necessarily-supported case. But that shouldn't preclude us from at least opting-in to the combined policy cache. Limiting it to the default provider seems overly restrictive. If we are "advanced" enough to roll our own provider, we should be able to understand the implications of opting into the cache with an improperly implemented provider. |
We need to restrict it but at the right layer. What we want to happen is that if the user does not override the default policy provider, they get the caching for free. If they do override it, then they need to opt in. I see a couple of options:
|
Yeah this is basically the same problem I ran into while testing, the fact that its hardcoded to a specific type lacks extensibility, alternatively could we just add a new setting to AuthorizationOptions, |
I don't think it should be an option. The marker interface lets the implementation opt in to the behavior. |
The other option is an default interface method: public interface IAuthorizationPolicyProvider
{
+ public bool CanCachePolicies => false;
} |
I like that idea: |
@HaoK Can we update the proposed API to what we merged so we can discuss it in todays API review? |
I updated it. |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
API Review Notes:
API Approved! namespace Microsoft.AspNetCore.Authorization;
public interface IAuthorizationPolicyProvider
{
+ public bool AllowsCachingPolicies => false;
}
public class AuthorizationMiddleware
{
+ public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider, IServiceProvider services);
} |
Uh oh!
There was an error while loading. Please reload this page.
Background and Motivation
From @HaoK: We want to add a new metadata class which if applied to an endpoint, the authorization middleware will store the combined policy in this metadata to avoid recomputing the policy on every request (but only if the default policy provider is being used). The benefit for this being public is so anyone can benefit from this behavior by adding it to an endpoints metadata.
Proposed API
Usage Examples
Alternative Designs
Keep this internal for now and only use it from AuthorizationMiddleware.
Risks
We might want to change this class in the future and will be unable to make breaking changes since the metadata is now public.
PR for context: #43124
This is a follow up to the previously-approved
RequireAuthorization
overloads supporting inline policies: #39840The text was updated successfully, but these errors were encountered: