Skip to content
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

Authenticated response caching is not supported? #6836

Closed
jholovacs opened this issue Jun 3, 2018 — with docs.microsoft.com · 18 comments
Closed

Authenticated response caching is not supported? #6836

jholovacs opened this issue Jun 3, 2018 — with docs.microsoft.com · 18 comments
Labels
Source - Docs.ms Docs Customer feedback via GitHub Issue
Milestone

Comments

Copy link

Why? It seems quite silly to make the assumption that authenticated clients would not want or need a caching mechanism. How much of what we do with web api's does not require authentication?


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@Rick-Anderson Rick-Anderson added Source - Docs.ms Docs Customer feedback via GitHub Issue question labels Jun 3, 2018
@Rick-Anderson Rick-Anderson added this to the Backlog milestone Jun 3, 2018
@Rick-Anderson
Copy link
Contributor

@jholovacs is this your question?

Warning

Disable caching for content that contains information for authenticated clients. Caching should only be enabled for content that doesn't change based on a user's identity or whether a user is signed in.

@jholovacs
Copy link
Author

jholovacs commented Jun 3, 2018 via email

@Rick-Anderson
Copy link
Contributor

The warning says Disable caching for content that contains information for authenticated clients. that's it. It doesn't stop you from doing that. It's telling you not to enable caching containing information (personal information, etc).

See https://docs.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.1

@jholovacs
Copy link
Author

jholovacs commented Jun 3, 2018 via email

Copy link

zihotki commented Oct 1, 2018

I also don't quite understand reasons why caching for authenticated clients is not supported. IMO there are no reasons to not support it for particular authenticated client (like VaryByApiKey with possible combination with other VaryByQuery). It seems like a valid scenario to me. Can somebody please elaborate?
Also from what I know when you use standard middleware for response caching it won't cache authenticated responses, according https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-2.1#conditions-for-caching . Documentation implicitly tells to not use caching in such scenario without why's or guidance of enabling proper caching of authenticated requests.

@Rick-Anderson
Copy link
Contributor

Thanks for contacting us.
We don’t have the resources to invest in this area, so we are closing the issue. Should your request generate enough 👍 responses, we’ll reconsider.

@ErikNoren
Copy link

I think that warning is general to HTTP caching concerns, not specific to ASP.NET Core. This document explains how to implement caching in ASP.NET Core for a person who knows what they're trying to accomplish. Information on HTTP caching, potential issues, etc. are quite extensive and would appear to be outside the scope of this document. It might be good if the warning had a link out to a resource that explains the issue though so people could more easily get the information they need to resolve the concern the warning raises.

From what I would guess though, this is referencing the proxy cache problem (which might also be a problem with the middleware server-side caching). To illustrate one example:

User A makes a request to server using a general URL.

Server sees User A has made the request and responds with data customized to what User A can see. It knows the content won't change for some time so it tacks on cache headers to let the browser know the response can be stored and future requests within a certain time can be satisfied from the local cache.

A proxy appliance (or server-side caching middleware?) between the user and server observes the request and notes the response headers say the conent is static for some time.

User B makes a request to the server using the same general URL.

The proxy appliance notes the request exactly matches a previous requests, it notes is has a response cached that is still valid and responds with that. The server (your controller) is never aware the request was made because the proxy handled it.

User B now has User A's data.

This problem used to be much worse a long time ago when sites didn't use HTTPS and proxy appliances were aggressive and misconfigured but it's still a potential issue in various situations and might be applicable to the server-side cache that responds directly without calling your controller methods. From the point of view of this document telling people how to configure the caching in ASP.NET Core, the warning is a good shortcut to make people aware there is a concern they should be aware of in case they didn't first start with understanding fully what and how HTTP caching works and is just expecting the library to take care of it all for them.

The doc would be improved by linking the warning to a more comprehensive document on caching and specifically the problem around authenticated (or really user-specific) content in my opinion to help people find a good explanation on the problem and the right way to handle it.

@zihotki
Copy link

zihotki commented Jan 7, 2019

A proxy appliance (or server-side caching middleware?) between the user and server observes the request and notes the response headers say the conent is static for some time.

Isn't 'private' cache control directive addresses that?

This problem used to be much worse a long time ago when sites didn't use HTTPS and proxy appliances were aggressive and misconfigured but it's still a potential issue in various situations and might be applicable to the server-side cache that responds directly without calling your controller methods.

But it's 2019 now, I assume all caching solutions have fully adopted the standard and it's not possible to have a completely bullet-proof solution since, like you said, proxy can be misconfigured and even apply cache for non-cachable private resources. IMO, Trying to workaround possible misconfigurations is a dead end, it's better to assume the standard.

And as far as I understand, the original question was not in regards with documentation but with the implementation. Currently it completely disables cache for such scenarios and even if you know what you are doing you'll not be able to configure it, you'll have to redo the whole caching layer.

@aseelawi
Copy link

its mentioned here as warning
https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-3.1

but it's mentioned clearly that its disabled in the middleware section "Authorization | The response isn't cached if the header exists." !
https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-3.1

however , I've tried it and it is working fine even if there is Authorization attribute on my controller .

the question here , is it OK to use VaryByHeader = "Authorization" to avoid mixing cached data between different users ?

@joaoantunes
Copy link

joaoantunes commented Jul 14, 2020

@aseelawi whenever I pass an Authorization header, it simply ignores the caching.
And that is written on the documentation

"The Authorization header must not be present."

I'm using OAuth Client Credentials Flow, to ensure the protection of the APIs. Is not a user authentication but a Machine!
So it should use caching because there is no difference in the requests/responses between different machines, but is this Microsoft rules I can't use their caching middleware.

So the only alternative that I see is to implement my own Middleware/Attributes.

@cdonner
Copy link

cdonner commented May 28, 2021

its mentioned here as warning
https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-3.1

but it's mentioned clearly that its disabled in the middleware section "Authorization | The response isn't cached if the header exists." !
https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-3.1

however , I've tried it and it is working fine even if there is Authorization attribute on my controller .

the question here , is it OK to use VaryByHeader = "Authorization" to avoid mixing cached data between different users ?

It is not caching for me in Dotnet 5. If I turn authentication off on the API, it caches. Very sad.

@gr8tushar
Copy link

Hi.
There are various use cases where in you would want to have caching for authenticated clients.
e.g. If there is an enterprise application which shows the list of users. You would want to cache the user image but for only authenticated user. The authentication for displaying the image is already there.
You would want to cache the logged in user name and won't want to refresh it on every request.
The company's logo in the secured area of the portal needs to be cached.

There would be hundreds of use cases where in you would want to cache values for authenticated users.

I hope the team looks at this issue seriously.

@magiak
Copy link

magiak commented May 3, 2022

The warning says Disable caching for content that contains information for authenticated clients. that's it. It doesn't stop you from doing that.

It's not true. I can not use ResponseCache with authorization header because one of the conditions for caching in response caching middleware is "The Authorization header must not be present.".

@MeikelLP
Copy link

MeikelLP commented Aug 3, 2022

Still valid to this day. Why can't I cache my static responses AND protect them. I don't really understand the reason behind this.

@jzs11
Copy link

jzs11 commented Sep 8, 2022

In .Net 7, you could implement a customised IOutputCachePolicy for minimal API and do caching as your wish. However, it needs lots of extra code to write such as varyByValue for the authenticated user, and when to invalidate the cache so on and so forth, which makes me feel try to improve the code and reduce the usage of cache for all is not a bad idea.

@CostasCF
Copy link

I will provide some code that worked for me. I used Bearer token authentication for protecting my api endpoints and used custom caching policy in order to save resources for my .net 7 web api.

First you create below custom cache policy class:

public class OutputCacheWithAuthPolicy : IOutputCachePolicy
{
    public static readonly OutputCacheWithAuthPolicy Instance = new();
    private OutputCacheWithAuthPolicy() { }

    ValueTask IOutputCachePolicy.CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        var attemptOutputCaching = AttemptOutputCaching(context);
        context.EnableOutputCaching = true;
        context.AllowCacheLookup = attemptOutputCaching;
        context.AllowCacheStorage = attemptOutputCaching;
        context.AllowLocking = true;

        // Vary by any query by default
        context.CacheVaryByRules.QueryKeys = "*";
        return ValueTask.CompletedTask;
    }
    private static bool AttemptOutputCaching(OutputCacheContext context)
    {
        // Check if the current request fulfills the requirements to be cached
        var request = context.HttpContext.Request;

        // Verify the method, we only cache get and head verb
        if (!HttpMethods.IsGet(request.Method) && !HttpMethods.IsHead(request.Method))
        {
            return false;
        }
        // we comment out below code to cache authorization response.
        // Verify existence of authorization headers
        //if (!StringValues.IsNullOrEmpty(request.Headers.Authorization) || request.HttpContext.User?.Identity?.IsAuthenticated == true)
        //{
        //    return false;
        //}
        return true;
    }
    public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellation) => ValueTask.CompletedTask;
    public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellation) => ValueTask.CompletedTask;

} 

Later, in Program.cs, you enable OutputCache with the above custom policy option:

builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder.Cache());
    options.AddPolicy("OutputCacheWithAuthPolicy", OutputCacheWithAuthPolicy.Instance);
});

app.UseOutputCache();

Then, above your specified endpoint inside your controller you place the below annotation above the endpoint you want to cache regardless of authorization headers (but enabled ofc!),
[OutputCache(Duration = 86400, PolicyName = "OutputCacheWithAuthPolicy")] // incicate policy name

And you are done!

@douglasg14b
Copy link

douglasg14b commented Jan 5, 2024

Kinda sucks that this problem is now in kindergarden, and we still cannot protect static outputs with built-in caching without customizing it (Which is now a maintenance burden) as a result of an artificial restriction... And it's not even recognized as a valid problem.

@6pac
Copy link

6pac commented Jun 17, 2024

@CostasCF Note that Output Caching and Response Caching are two separate issues.

Completely agree with previous comments. We should have this for Authorized pages. At least be able to write a policy to update the default one, like you can for Output Caching (the visibility of the necessary elements of the policy won't let this hapen for ResponseCache).

I'm currently in the process of trying to rewite the Response Caching object to do this. Bad idea, but left with no other option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Source - Docs.ms Docs Customer feedback via GitHub Issue
Projects
None yet
Development

No branches or pull requests