Search code examples
c#entity-frameworkidentityserver4openid

IdentityServer4 CORS Settings with EntityFramework


EDIT: I partially answered my question. For those who are curious, there is another table inside the database called ClientProperties that you can use to set other properties not on the main client table. I did this, but I still have an error: enter image description here

My entry for the client config looks like this: enter image description here

Working on it further (I manually defined the content policy), this is the error that is present that I am stuck at: enter image description here

--------------------- Original Question ---------------------

I have IdentityServer4 setup using EntityFramework for my configuration and operation data.

I ran into an issue when trying to allow ajax to handle the redirects when logging into an application. Instead of trying to hardcode everything, I was trying to setup CORS within IDS4.

I was reading the document HERE. It talks about setting up AllowedCorsOrigins on the client so that the identity server will correctly setup CORS. The issue I am having is that in the database, the clients do not have a column called AllowedCorsOrigins defined. In fact there are a lot of missing columns as defined on the openId model.

On my identity server, my DI configuration is as follows:

services.AddIdentity < IdentityUser, IdentityRole > ()
  .AddUserManager < ApplicationUserManager < IdentityUser >> ()
  .AddSignInManager < ApplicationSignInManager < IdentityUser >> ()
  .AddEntityFrameworkStores < ApplicationDbContext > ();

services.AddIdentityServer()
  .AddAspNetIdentity < IdentityUser > ()
  .AddConfigurationStore(options => {
    options.ConfigureDbContext = builder => builder.UseSqlServer(
      configuration.GetConnectionString("IdentityConnection"),
      opt => opt.MigrationsAssembly(startupName));
  })
  .AddOperationalStore(options => {
    options.ConfigureDbContext = builder => builder.UseSqlServer(
      configuration.GetConnectionString("IdentityConnection"),
      opt => opt.MigrationsAssembly(startupName));
  })
  .AddProfileService < ApplicationProfileService < IdentityUser >> ()
  .AddDeveloperSigningCredential();

And on my client the DI setup is as follows:

services.AddAuthentication(options => {
    options.DefaultScheme = "cookie";
    options.DefaultChallengeScheme = "oidc";
  }).AddCookie("cookie")
  .AddOpenIdConnect("oidc", options => {
    options.Authority = appSettings.App.AuthorityUrl;
    options.ClientId = appSettings.App.ClientId;
    options.ClientSecret = appSettings.App.ClientSecret;

    options.ResponseType = ResponseTypes.Code;
    options.UsePkce = true;
    options.ResponseMode = "query";

    options.GetClaimsFromUserInfoEndpoint = true;
    options.ClaimActions.MapJsonKey("role", "role", "role");
    options.ClaimActions.MapJsonKey("nickname", "nickname", "nickname");
    options.ClaimActions.MapJsonKey(JwtClaimTypes.Picture, JwtClaimTypes.Picture, JwtClaimTypes.Picture);
    options.TokenValidationParameters.RoleClaimType = "role";

    var test = options.ClaimActions;

    options.Scope.Add(appSettings.App.Scopes[0]);
    options.SaveTokens = true;
  });

I am having trouble figuring out where I should be defining the AllowedCorsOrigins as all of the examples I have seen are in memory examples. I would think this property should be in the database on the client table...

Here is a look at what values I have access to in the database:

Database Table

Finally this is the error in the console: Console Error


Solution

  • The issue lies with AJAX.

    Because I post a form to the login endpoint in MVC, the response can not be a 302 redirect. This is because AJAX does not allow redirects on posts.

    To fix this, I am now returning a JSON object with the return URL and having javascript set the window.location value instead. The following is an example of this (Note I am checking if it is a JSON object first because this handler handles multiple ajax calls).

    if (xhr.responseText.startsWith('{')) {
        let json = JSON.parse(xhr.responseText);
        if (json.ok) {
            window.location = json.redirect;
            return;
        }
    }