Reputation: 117146
I have an Asp .net mvc app that connects to an Identity server 4 identity server. When i released the app I was fased with this error.
upstream sent too big header while reading response header from upstream
Which i have tracked to this upstream sent too big header while reading response header from upstream
I can not alter the config and sys admin has stated that we need to make the headers smaller.
After looking at that i would have to agree that these headers are a bit extensive.
Startup.cs in app
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = Configuration["ServiceSettings:IdentityServerEndpoint"];
options.RequireHttpsMetadata = true;
options.ClientId = Configuration["ServiceSettings:ClientId"];
options.ClientSecret = Configuration["ServiceSettings:secret"];
options.Scope.Add("testapi");
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Events = new OpenIdConnectEvents()
{
OnRemoteFailure = ctx =>
{
_logger.LogCritical($"Remote Faliure: {ctx.Failure}");
ctx.HandleResponse();
return Task.FromResult(0);
}
};
});
I have been looking all over and i cant seem to find a way of limiting the size of this huge header.
Upvotes: 5
Views: 4047
Reputation: 101543
By default, cookie contains all relevant information, encrypted, so when call to your api is made - all you need to do is decrypt cookie and use that information.
However, often storing everything in a cookie itself is not desirable, especially if there is a lot of relevant information. Cookie is sent with every request to your api, and if it's big - a lot of (the same) information is sent back and forth basically for nothing. Plus as you see yourself - size of cookie might become a limiting factor in some environments.
So instead of sending all information in cookie itself - you can store that information somewhere else, for example in server memory, and place only identifier for that information in cookie itself.
You can configure store for session like this:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(o => o.SessionStore = new MemoryCacheTicketStore());
And you can find sample MemoryCacheTicketStore
implementation at asp.net examples on github:
public class MemoryCacheTicketStore : ITicketStore
{
private const string KeyPrefix = "AuthSessionStore-";
private IMemoryCache _cache;
public MemoryCacheTicketStore()
{
_cache = new MemoryCache(new MemoryCacheOptions());
}
public async Task<string> StoreAsync(AuthenticationTicket ticket)
{
var guid = Guid.NewGuid();
var key = KeyPrefix + guid.ToString();
await RenewAsync(key, ticket);
return key;
}
public Task RenewAsync(string key, AuthenticationTicket ticket)
{
var options = new MemoryCacheEntryOptions();
var expiresUtc = ticket.Properties.ExpiresUtc;
if (expiresUtc.HasValue)
{
options.SetAbsoluteExpiration(expiresUtc.Value);
}
options.SetSlidingExpiration(TimeSpan.FromHours(1)); // TODO: configurable.
_cache.Set(key, ticket, options);
return Task.FromResult(0);
}
public Task<AuthenticationTicket> RetrieveAsync(string key)
{
AuthenticationTicket ticket;
_cache.TryGetValue(key, out ticket);
return Task.FromResult(ticket);
}
public Task RemoveAsync(string key)
{
_cache.Remove(key);
return Task.FromResult(0);
}
}
Upvotes: 6