Azure AD – Request Too Long

I’ve been getting to grips with Azure AD authentication an part of that has involved retrieving access codes for Power BI at initial login to an authenticated web application. When I finally managed to get this working I then started getting the following error.

Bad Request - Request Too Long
HTTP Error 400. The size of the request headers is too long.

This is caused because the TokenCache is stored as a cookie and the sheer size of it is greater than can be transmitted in the request headers, this is the case even though I was only requesting two scopes.

The solution which came from this stackoverflow answer is to store the tokens in memory rather than transmitting back and forth as part of the request.

MemoryCacheTicketStore.cs

	
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);
	}
}
	

This can then be used to store the session cookies in the sites startup file.

Startup.cs

	
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
	services.Configure<CookiePolicyOptions>(options =>
	{
		// This lambda determines whether user consent for non-essential cookies is needed for a given request.
		options.CheckConsentNeeded = context => false;
		options.MinimumSameSitePolicy = SameSiteMode.None;
	});

	// Add session
	services.AddSession();

	services.AddAuthentication(sharedOptions =>
	{
		sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
		sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
	})
	.AddAzureAd(options => Configuration.Bind("AzureAd", options))
	.AddCookie(options =>
	{
		options.SessionStore = new MemoryCacheTicketStore();
	});

	// Token service
	services.AddTokenAcquisition();

	services.AddMvc(options =>
	{
		var policy = new AuthorizationPolicyBuilder()
			.RequireAuthenticatedUser()
			.Build();
		options.Filters.Add(new AuthorizeFilter(policy));
	})
	.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
	

Leave a Reply

Your email address will not be published. Required fields are marked *