Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 6 OpenIdConnect

I am currently running into multiple issues migrating my MVC application from beta 3 to 4 - one of these has to do with OpenIdConnect to Windows Azure for authentication. When I go to a page that has an Authorize attribute, the page stops processing and sits at a blank white page without bringing up the Azure sign in page. I do not get a YSOD - just the blank screen. As for sample code, I've only been able to find these: https://github.com/aspnet/Security/blob/5cf0564484cf5bb2a7a16e6485816d19287538e6/samples/OpenIdConnectSample/Startup.cs https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/vNext/samples/Mvc/Mvc.Client/Startup.cs

If I use the second example, and actually use the ChallengeResult in a different controller, it does bring up the Azure Sign In page but brings back a Bad Request (400) on Azure side.

This is my current code:

public void ConfigureServices(IServiceCollection services)
{
    // Cannot find services.AddAuthentication that is supposed to be in Microsoft.Framework.DependencyInjection
    services.AddWebEncoders(); 
    services.AddDataProtection();

services.Configure<ExternalAuthenticationOptions>(options =>
{
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationType;
});

// Add MVC services to the services container.
services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
    // Configure the OWIN Pipeline to use OpenID Connect Authentication
    app.UseCookieAuthentication(options => { 
        options.AutomaticAuthentication = true;
    });

    app.UseOpenIdConnectAuthentication(options =>
    {
        options.ClientId = Constants.ClientId;
        options.Authority = Constants.Authority;
        options.PostLogoutRedirectUri = Constants.PostLogoutRedirectUri;
        options.TokenValidationParameters.RoleClaimType = "roles";

        options.Notifications = new OpenIdConnectAuthenticationNotifications()
        {
              AuthorizationCodeReceived = async (context) =>
              {
                  var code = context.Code;

                  ClientCredential credential = new ClientCredential(Constants.ClientId, Constants.AppKey);

                  AuthenticationContext authContext = new AuthenticationContext(Constants.Authority, false);
                  var result = await authContext.AcquireTokenByAuthorizationCodeAsync(
                            code, new Uri(Constants.PostLogoutRedirectUri), credential, Constants.GraphUri);
                  ActiveDirectoryHelper.token = result.AccessToken;
                }
          };
     });

     // More MVC stuff such as routing and static files
}

P.S. Does anyone have any helpful resources for MVC 6? I've been scouring GitHub for most of my Beta 4 code.

like image 394
Steven Mayer Avatar asked Sep 28 '22 23:09

Steven Mayer


1 Answers

The problem you are having is related to the Cookie header and it's beyond the limit of HTTP.sys if the 400 error you are getting is "HTTP Error 400. The size of the request headers is too long.". The Azure AD cookie header probably exceeds the limit for a single header. I had the same issue and here was my cookies:

ARRAffinity = 65 bytes

.AspNet.Cookies = 9 bytes

.AspNet.CookiesC1 = 4046 bytes

.AspNet.CookiesC2 = 4046 bytes

.AspNet.CookiesC3 = 4046 bytes

.AspNet.CookiesC4 = 3850 bytes

You will probably see a similar picture. There are couple of workarounds:

  1. If you have control over the server, apply these registry changes to bump the limit and restart your server.

  2. If you don't have control over the server (e.g. Azure Web Apps), you need to shrink down the size of the cookie. To do this, you can store the cookie content on the ASP.NET 5 session and instead, store the session cookie which is way smaller. Example:

    app.UseCookieAuthentication(options =>
    {
        options.AutomaticAuthentication = true;
        options.SessionStore = new MemoryCacheSessionStore();
    });
    

    MemoryCacheSessionStore here is an implementation of IAuthenticationSessionStore. You can find the complete sample here on ASP.NET Security repository.

like image 50
tugberk Avatar answered Oct 07 '22 19:10

tugberk