In my previous question, I asked a generic question how to add permission for static content. Here I want to be more precise.
In my project I added a folder under wwwroot to simplify the code, where I save the html files I want to protect. This folder is called infographics.
The properties for each file are:
Build Action: Content
Copy to Output Directory: Do not copy
Follow the instruction from the Microsoft documentation, I changed the Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.Configure<IdentityServerConfiguration>(Configuration.GetSection("IdentityServerConfiguration"));
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.Cookie.Name = ".my.Session";
options.IdleTimeout = TimeSpan.FromHours(12);
});
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
options.Cookie.Name = "my.dashboard";
})
.AddOpenIdConnect("oidc", options =>
{
IdentityServerConfiguration idsrv = Configuration.GetSection("IdentityServerConfiguration")
.Get<IdentityServerConfiguration>();
options.Authority = idsrv.Url;
options.ClientId = idsrv.ClientId;
options.ClientSecret = idsrv.ClientSecret;
#if DEBUG
options.RequireHttpsMetadata = false;
#else
options.RequireHttpsMetadata = true;
#endif
options.ResponseType = "code";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("roles");
options.Scope.Add("offline_access");
options.ClaimActions.MapJsonKey("role", "role", "role");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.SignedOutRedirectUri = "/";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
if (ctx.Context.Request.Path.StartsWithSegments("/infographics"))
{
ctx.Context.Response.Headers.Add("Cache-Control", "no-store");
if (!ctx.Context.User.Identity.IsAuthenticated)
{
// respond HTTP 401 Unauthorized with empty body.
ctx.Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
ctx.Context.Response.ContentLength = 0;
ctx.Context.Response.Body = Stream.Null;
// - or, redirect to another page. -
// ctx.Context.Response.Redirect("/");
}
}
}
});
app.UseRouting();
app.UseAuthorization();
app.UseCookiePolicy();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
What I expect is when the user asks for /infographics the OnPrepareResponse verifies the request and if the user is authenticated sees the page. But, after a lot of code changing, the result is always the same (on my local machine):
This localhost page can’t be found
I tried to add this code to map the folder html in the root of the project as infographics but without success.
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "html")),
RequestPath = "/infographics"
});
Any ideas?
Update
This is working with not HTML files. I think the problem comes from the HTML file because they are static content for ASP.NET.
I put a breakpoint on the OnPrepareResponse and call the page infographics/index.html. The page is displayed (red arrow) and then the application stops on the breakpoint (blue arrow).
For any one else that ends up here searching for protecting secure static files.
For .NET Core 5. Documentation has been updated to include how to handle this
Per the documentation:
To serve static files based on authorization:
Store them outside of wwwroot.
Call UseStaticFiles, specifying a path, after calling UseAuthorization.
Set the fallback authorization policy.
Make sure to add a fallback policy as well:
services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
See: Static file authorization
I would recommend to place that folder outside the wwwroot folder, which will remove the static file access to it.
You can then serve your files from a controller like so:
public IActionResult GetInfographic(string name)
{
var infographicPath = resolvePath(name);
return new FileStreamResult(new FileStream(infographicPath, FileMode.Open, FileAccess.Read), mime);
}
given this is a controller you can use the [Authorize] tag to secure it any way you'd like.
Related
I've just created a new ASP.NET Core application using Visual Studio, it has the authentication type set to "Individual Accounts":
I've added some code to handle OIDC:
builder.Services.AddAuthentication().AddOpenIdConnect(openIdOptions =>
{
openIdOptions.ClientId = "myClientId";
openIdOptions.Authority = "myAuthority";
openIdOptions.ResponseType = OpenIdConnectResponseType.Code;
openIdOptions.GetClaimsFromUserInfoEndpoint = false;
openIdOptions.CallbackPath = "/signin-oidc";
openIdOptions.SaveTokens = true;
Which is all well and good, I can click to login with OpenIdConnect:
When I log in with the provided credentials it pops up asking me to Associate my OpenIdConnect account:
I don't want to have to do this. Retrieving the access token and id token is sufficient for what I want to do, I don't require a local copy of the user. Being new to ASP.net and having not used Razor before it's not immediately obvious what code I should delete — if that's even the correct approach. I've played around with deleting various bits such as the Db setup as I don't really require it, although I suspect Razor does in some regard.
The Program.cs looks as follows:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
{
})
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddAuthentication().AddGoogle(googleOptions =>
{
googleOptions.ClientId = builder.Configuration["Authentication:Google:ClientId"];
googleOptions.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
});
builder.Services.AddAuthentication().AddOpenIdConnect(openIdOptions =>
{
openIdOptions.ClientId = "clientId";
openIdOptions.Authority = "authority";
openIdOptions.ResponseType = OpenIdConnectResponseType.Code;
openIdOptions.GetClaimsFromUserInfoEndpoint = false;
openIdOptions.CallbackPath = "/signin-oidc";
openIdOptions.SaveTokens = true;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}"); });
app.Run();
I installed AWS Toolkit for Visual Studio 2019 & created new "AWS Serverless Application(.NET Core C#)" project.
Following this video tutorial I configured new Cognito User Pool & edited the default project's Startup.cs & added secure page with [Authorize] attribute (at the 12min mark you can find the exact steps of how Cognito was configured).
After publishing to AWS (or even when debugging locally) when I navigate to secure page I correctly get redirected and prompted to login, but after successful login it enters a loop in the background that keeps sending back to OIDC authorization link & back to my site... after a few of those it throws an error of "ERR_TOO_MANY_REDIRECTS".
Any idea what is missing from this tutorial in order to make it work properly? The only step I skipped was that he registered a domain name for his site, while I'm just using the default site URL I get after right-clicking project & choosing "Publish to AWS Lambda".
Here's edited code of my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
string clientId = "<cognito_app_client_id>";
string clientSecret = "<cognito_app_client_secret>";
string logoutUrl = "https://<published_app_aws_url>/logout";
string baseUrl = "https://<published_app_aws_url>";
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.ResponseType = OpenIdConnectResponseType.Code;
options.MetadataAddress = $"https://cognito-idp.<aws_region>.amazonaws.com/<cognito_pool_id>/.well-known/openid-configuration";
options.ClientId = clientId;
options.ClientSecret = clientSecret;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("email");
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProviderForSignOut = (context) =>
{
var logoutUri = logoutUrl;
logoutUri += $"client_id={clientId}&logout_uri={baseUrl}";
context.Response.Redirect(logoutUri);
context.HandleResponse();
return Task.CompletedTask;
}
};
});
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
Thanks to comment by Philip Pittle I found the UseAuthentication must come before UseAuthorization.
I have I am using ID4 for OIDC and ASP.Net Core Identity to manage the user membership. Razor with Pagemodel. I have a test client that properly logs in with SSO. On logout , it log outs of the client OK, but does not logout from the ID4 server.
On Logout, the client redirects to my ID4 server using the end session url. It does have hint token. The ID4 server does show the logout page, but it still is logged in. I suspect the problem is that I am using scafolded ASP.Net Identity pages for login/logout.
Manually clicking on the logout button on the ID4 server works as expected. The user is logged on on the server and on the client.
I am able to get it to work by redirecting to the ASP.Net Core Indentity logout page and have the OnGet method call _signInManager.SignOutAsync(). But this seems like a poor solution to me.
Reading the ID4 docs, spec and many github and SO posts, I have the following logout code on my client:
var id_token = (await HttpContext.AuthenticateAsync()).Properties.Items[".Token.id_token"];
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
var redirectUrl = $"{Startup.IdentityServerUrl}/connect/endsession?id_token_hint={id_token}";
return Redirect(redirectUrl);
And here is the startup code for my client:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = IdentityServerUrl;
options.RequireHttpsMetadata = false;
options.ClientId = "testClient1";
options.ClientSecret = "xxxxxxxxxxxxx";
options.ResponseType = "code";
options.SaveTokens = true;
});
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapDefaultControllerRoute()
.RequireAuthorization();
});
}
Here is the startup code for my ID4 server:
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("DefaultConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
services.AddIdentity<ApplicationUser, IdentityRole>(
config =>
{
config.SignIn.RequireConfirmedEmail = true;
config.SignIn.RequireConfirmedAccount = true;
config.User.RequireUniqueEmail = true;
config.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
config.Lockout.MaxFailedAccessAttempts = 5;
config.Lockout.AllowedForNewUsers = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// these point ID4 to the correct pages for login, logout, etc.
services.ConfigureApplicationCookie((options) =>
{
options.LoginPath = "/Identity/Account/Login";
options.LogoutPath = "/Identity/Account/Logout";
options.AccessDeniedPath = "/Error";
});
services.AddIdentityServer()
.AddOperationalStore(options =>
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
.AddConfigurationStore(options =>
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
.AddAspNetIdentity<ApplicationUser>()
.AddDeveloperSigningCredential();
ConfigureEmailServices(services);
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
InitializeDbTestData(app);
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseIdentityServer();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
For the idp logout you don't need to redirect manually. Simply return a SignOutResult and the redirection will be done by the oidc handler by using discovery endpoint and mounting the request properly. Put this code in your logout method:
return SignOut(new[] { "Cookies", "oidc" });
Or this other:
return new SignOutResult(new[] { "Cookies", "oidc" });
If you want to be redirected to the client after the idp logout, set up your postLogoutRedirectUri.
I'm using IdentityServer 4 to provide authentication and autorisation for my web app, using an external login provider (Microsoft).
This works fine when I run both IdentityServer and my web app locally.
However, when I publish the Identityserver project to Azure, it no longer works.
When I connect my locally running web app to the published IdentityServer, after returning from the Microsoft login page, the web app fails with the error 'Correlation failed. unknown location'.
The output from the web app shows:
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:
Warning: '.AspNetCore.Correlation.oidc.xxxxxxxxxxxxxxxxxxx' cookie not found.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:
Information: Error from RemoteAuthentication: Correlation failed..
However, when I check my browser, a cookie with the exact name '.AspNetCore.Correlation.oidc.xxxxxxxxxxxxxxxxxxx' does exist..
Here's the startup.cs from the web app:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services
.AddTransient<ApiService>();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie()
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = Configuration.GetSection("IdentityServer").GetValue<string>("AuthorityUrl");
//options.RequireHttpsMetadata = true;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("api1");
options.Scope.Add("offline_access");
});
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("nl-NL"),
new CultureInfo("en-US")
};
options.DefaultRequestCulture = new RequestCulture("nl-NL", "en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller}/{action}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
For me, Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler was logging this error:
'".AspNetCore.Correlation.OpenIdConnect.84ee_7zFbvb_w264b0SPRmS1OTKCeDhmzQ6awHoJ5gA"' cookie not found.
After looking at Chrome developer tools, I could see that the Correlation cookie was being stripped by the browser because the cookie's SameSite attribute was set to "None" yet the "Secure" attribute was not set. Chrome didn't like this.
I added the following statement in my Startup.Configure method.
*NOTE: This has to be added before app.UseAuthentication() and app.UseAuthorization().
app.UseCookiePolicy(new CookiePolicyOptions
{
Secure = CookieSecurePolicy.Always
});
I have resolved this issue by adding below code
options.Events = new OpenIdConnectEvents
{
OnMessageReceived = OnMessageReceived,
OnRemoteFailure = context => {
context.Response.Redirect("/");
context.HandleResponse();
return Task.FromResult(0);
}
};
The problem was that the IdentityServer was still using AddDeveloperSigningCredential
which worked fine locally, but not in Azure.
By adding a certicate and this code it worked perfectly:
X509Certificate2 cert = null;
using (X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
// Replace below with your cert's thumbprint
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
false);
// Get the first cert with the thumbprint
if (certCollection.Count > 0)
{
cert = certCollection[0];
Log.Logger.Information($"Successfully loaded cert from registry: {cert.Thumbprint}");
}
}
// Fallback to local file for development
if (cert == null)
{
cert = new X509Certificate2(Path.Combine(_env.ContentRootPath, "example.pfx"), "exportpassword");
Log.Logger.Information($"Falling back to cert from file. Successfully loaded: {cert.Thumbprint}");
}
Finally I fixed it by
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.None
});
Before applying the change, I noticed the cookie's same site was marked as Strict.
I changed the code to SameSiteMode.Lax, and it didn't work.
So I changed again to the SameSiteMode.None, it works!
Make sure the user didn't bookmark your login page instead of your home page. This was the problem I had with Cognito.
In order to get it working, I had to combine Jeff Tian's solution with Scope Creep's solution:
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.None,
Secure = CookieSecurePolicy.Always
});
Then I also had to add an extra line to ConfigureServices:
options.Cookie.SameSite = SameSiteMode.None;
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.None; // I ADDED THIS LINE!!!
options.LoginPath = "/home/NotAuthorized";
...
Turning on Sessions in Asp.net also fixes the issue, and MayankGaur's solution also works, but I really didn't want to suppress errors that might make things easier to debug in the future.
I am trying to create an authentication on an ASP.NET Core 2.0 web app.
My company is using Ping Federate and I am trying to authenticate my users using the company login page and in return validating the returned token using my signing key (X509SecurityKey down here).
The ping login link link looks like:
https://auth.companyname.com
I configured the Startup.cs to be able to log in and challenge against this site.
I decorated my HomeController with a [Authorize(Policy="Mvc")].
I am able to reach the login page, but, whenever I return from it I get (
I tried turning off/on multiple multiple validations):
Exception: Correlation failed.
Unknown location
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()
The error message is not very helpful... anybody encountered such an issue before?
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = PF_LOGINPATH;
options.ClientId = Configuration["ClientId"];
options.ClientSecret = Configuration["ClientSecret"];
options.Scope.Clear();
options.ResponseType = OpenIdConnectResponseType.CodeIdTokenToken;
options.SaveTokens = false;
options.GetClaimsFromUserInfoEndpoint = false;//true;
options.TokenValidationParameters = new TokenValidationParameters
{
RequireSignedTokens = false,
ValidateActor = false,
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = false,
ValidateTokenReplay = false,
// Compensate server drift
ClockSkew = TimeSpan.FromHours(24),
//ValidIssuer = PF_LOGINPATH;
// Ensure key
IssuerSigningKey = CERTIFICATE,
// Ensure expiry
RequireExpirationTime = false,//true,
ValidateLifetime = false,//true,
// Save token
SaveSigninToken = false
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Mvc", policy =>
{
policy.AuthenticationSchemes.Add(OpenIdConnectDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
});
}
// 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.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
I had similar situation. My Application url is like this : "https://domain/appname"
so when someone types url "https://domain/appname/" [with trailling slash], it gives Correlation error. This is how I have resolved it (found from some oher site)
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
//Auth schemes here
})
.AddOpenIdConnect(oid =>
{
//Other config here
oid.Events = new OpenIdConnectEvents()
{
OnRemoteFailure = OnRemoteFailure
};
});
}
private Task OnRemoteFailure(RemoteFailureContext context)
{
if (context.Failure.Message.Contains("Correlation failed"))
{
context.Response.Redirect("/AppName"); // redirect without trailing slash
context.HandleResponse();
}
return Task.CompletedTask;
}
end your callback url with a slash