I have an MVC Razor pages app which I want to hook into our Identity Server Implementation. We have followed the tutorial in their quickstart https://identityserver4.readthedocs.io/en/latest/quickstarts/2_interactive_aspnetcore.html and got it working in a brand new project, so we assume the client and IDS configuration is OK.
However, when we port it into our RazorPages application we get into a loop. We are sent off to the IDS, we log in and we're sent back to the signin-oidc page. This page seems to generate a 302.
Please see this network trace. Each time the request is made a new "code_challenge" parameter is requested
My startup is (sorry long and) here:
public void ConfigureServices( IServiceCollection services )
{
services.AddIdentity<ApplicationUser, IdentityRole>( options =>
{
options.SignIn.RequireConfirmedEmail = true;
} )
.AddEntityFrameworkStores<CourseRegContext>()
.AddDefaultTokenProviders();
var cs = Configuration.GetConnectionString( "DefaultConnection" );
var skipHTTPS = Configuration.GetValue<bool>( "LocalTest:skipHTTPS" );
services.Configure<MvcOptions>( options =>
{
if ( /*Environment.IsDevelopment() && */!skipHTTPS )
{
options.Filters.Add( new RequireHttpsAttribute() );
options.EnableEndpointRouting = false;
}
} );
services.AddMvc()
.SetCompatibilityVersion( CompatibilityVersion.Version_2_1 )
.AddNewtonsoftJson(
options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
services.AddMvc( config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add( new AuthorizeFilter( policy ) );
config.EnableEndpointRouting = false;
} ).AddRazorPagesOptions( options =>
{
options.Conventions.AllowAnonymousToFolder( "/Oops" );
options.Conventions.AuthorizeFolder( "/Test" );
} );
services.AddMemoryCache();
services.AddHttpsRedirection( options =>
{
options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
if ( Environment.IsDevelopment() )
{
options.HttpsPort = 44311;
}
else
{
options.HttpsPort = 443;
}
} );
services.AddHsts( options =>
{
options.Preload = true;
options.IncludeSubDomains = true;
options.MaxAge = TimeSpan.FromHours( 1 );
} );
AddAuthorisation( services );
}
private void AddAuthorisation( IServiceCollection services )
{
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication( options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
} )
.AddCookie( "Cookies" )
.AddOpenIdConnect( "oidc", options =>
{
options.Authority = "https://localhost:41012";
options.ClientId = "validId";
options.ClientSecret = "somesecret";
options.ResponseType = "code";
options.Scope.Add( "roles" );
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
//options.UsePkce = true;
} );
//services.AddAuthorization();
services.AddAuthorization( options =>
{
options.AddPolicy( AuthPolicies.GlobalAdmin, policy =>
policy.RequireRole( ApplicationRoles.Administrator ) );
options.AddPolicy( AuthPolicies.CourseAdmin, policy =>
policy.RequireRole(
ApplicationRoles.Administrator,
ApplicationRoles.CourseAdmin ) );
options.AddPolicy( AuthPolicies.Presenter, policy =>
policy.RequireRole( ApplicationRoles.CourseViewer ) );
options.AddPolicy( AuthPolicies.UserAdmin, policy =>
policy.RequireRole( ApplicationRoles.UserAdmin, ApplicationRoles.Administrator ) );
} );
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure( IApplicationBuilder app, IHostingEnvironment env )
{
if ( env.IsDevelopment() )
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler( "/Oops/C500" );
app.UseHsts( options => options.MaxAge( hours: 1 ).IncludeSubdomains() ); //todo when confident it is working, use 180 days
}
app.UseStatusCodePagesWithRedirects( "/Oops/C{0}" );
app.UseXXssProtection( options => options.EnabledWithBlockMode() );
app.UseXContentTypeOptions();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints( endpoints =>
{
//endpoints.MapDefaultControllerRoute()
//.RequireAuthorization();
} );
app.UseMvc();
}
I wonder if it is something do with MVC and EndPoints as part of the upgrade to .NET Core 3.1, but I am unsure how to keep the rest of the project working and yet still get the IDS integration.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…