How to allow Caching API endpoint that requires Authorization header?
Asked Answered
K

2

10

I was looking at a way for caching responses from an API endpoint developed in .NET Core. The request to the API must have a valid Authorization header as part the requirement.

I came across a few articles mentioning that caching wouldn't be possible if the request contains Authorization header, which was a bit of surprise to me.

Response caching conditions

So how should I tackle this problem? Are there any libraries that can possibly enable caching for this kind of scenario?

Kansas answered 14/8, 2019 at 9:29 Comment(4)
It shouldn't be too much of a surprise :) Different users might be able to get different data, and caching those requests by default would create potential data leaks. There might be a setting for controlling that behaviour.Reprobate
FYI: "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." learn.microsoft.com/en-us/aspnet/core/performance/caching/…Surplice
@Reprobate - Thanks. It makes sense. But the tricky bit here in my case is that the Auth header must be required, even though the response data isn't user specific, e.g. static custom type and category enums, etc.Kansas
@Surplice - thanks. pls see my comments aboveKansas
P
6

For The Authorization header must not be present., this is by default.

For ResponseCachingMiddleware which will call IResponseCachingPolicyProvider to check whether to cache the reponse by if (_policyProvider.AllowCacheStorage(context)) like below:

// Should we store the response to this request?
if (_policyProvider.AllowCacheStorage(context))
{
    // Hook up to listen to the response stream
    ShimResponseStream(context);

    try
    {
        await _next(httpContext);

        // If there was no response body, check the response headers now. We can cache things like redirects.
        await StartResponseAsync(context);

        // Finalize the cache entry
        await FinalizeCacheBodyAsync(context);
    }
    finally
    {
        UnshimResponseStream(context);
    }

    return;
}

And, ResponseCachingPolicyProvider will check HeaderNames.Authorization by

public virtual bool AttemptResponseCaching(ResponseCachingContext context)
{
    var request = context.HttpContext.Request;

    // Verify the method
    if (!HttpMethods.IsGet(request.Method) && !HttpMethods.IsHead(request.Method))
    {
        context.Logger.RequestMethodNotCacheable(request.Method);
        return false;
    }

    // Verify existence of authorization headers
    if (!StringValues.IsNullOrEmpty(request.Headers[HeaderNames.Authorization]))
    {
        context.Logger.RequestWithAuthorizationNotCacheable();
        return false;
    }

    return true;
}

For ResponseCachingPolicyProvider, it is internal which you could not change from outside Microsoft.AspNetCore.ResponseCaching. It is not recommended to enable cache for Authorization, if you insist on, you could implement your own ResponseCachingMiddleware by refer ResponseCaching.

Proselytism answered 15/8, 2019 at 6:17 Comment(2)
Can you please help us to implement that middleware?Bryson
@JulianGr a bit late, but see below.Meathead
M
0

Firstly you must work out whether you need server side caching or client side caching, or both. If you need only client side caching, you just need to add the cache-control header to the response.
If you need server side caching, then you will need ResponseCache or OutputCache middleware.

I have written blog post about both client caching and the broader issues here.

If you need server caching, then there is a repo here that is the default version of the AspNet Core ResponseCache middleware, but with a AllowAuthorizedEndpoint flag added.

Meathead answered 1/9 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.