I am trying to get started with 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 login page link looks like:
https://companyname.com/authorization.oauth2?response_type=code&redirect_uri=https%3a%2f%2fJWTAuthExample%2fAccount%2fLogin&client_id=CompanyName.Web.JWTAuthExample&scope=&state=<...state...>
Out of the box, 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")]
but when I access one of the pages, I just get a blank page.
Debug is not hitting the OnChallenge
or OnAuthenticationFailed
methods when I add it to options.Events
(I think because user needs to be authenticated first).
So, what am I missing in order for a redirect to my authentication website to happen? Is it built in or do I have to do some manual configuration?
(Note: In other web apps, using asp net framework, I use a redirect in an Authorize attribute when authentication fails)
Related post: Authorize attribute does not redirect to Login page when using .NET Core 2's AddJwtBearer - From this post, does it mean I am not using the right authentication method? I am building a web app, not an API.
namespace JWTAuthExample
{
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
{
Configuration = configuration;
HostingEnvironment = hostingEnvironment;
string certificatepath = Path.Combine(HostingEnvironment.ContentRootPath, $"App_Data\\key.cer");
KEY = new X509SecurityKey(new X509Certificate2(certificatepath));
}
public IConfiguration Configuration { get; }
public IHostingEnvironment HostingEnvironment { get; }
private string AUTH_LOGINPATH { get; } = Configuration["DefaultAuth:AuthorizationEndpoint"];
private X509SecurityKey KEY { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.IncludeErrorDetails = true;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
// Ensure token expiry
RequireExpirationTime = true,
ValidateLifetime = true,
// Ensure token audience matches site audience value
ValidateAudience = false,
ValidAudience = AUTH_LOGINPATH,
// Ensure token was issued by a trusted authorization server
ValidateIssuer = true,
ValidIssuer = AUTH_LOGINPATH,
// Specify key used by token
RequireSignedTokens = true,
IssuerSigningKey = KEY
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Mvc", policy =>
{
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
});
}
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?}");
});
}
}
}
Following Brad's suggestion,
Here is a sample of code to perform an OpenId Connect confirguration on ASP NET 2.0
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 = Configuration["AuthoritySite"];
options.ClientId = Configuration["ClientId"];
options.ClientSecret = Configuration["ClientSecret"];
options.Scope.Clear();
// options.Scope.Add("Any:Scope");
options.ResponseType = OpenIdConnectResponseType.CodeIdTokenToken;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.TokenValidationParameters = new TokenValidationParameters
{
// Compensate server drift
ClockSkew = TimeSpan.FromHours(12),
// Ensure key
IssuerSigningKey = CERTIFICATE,
// Ensure expiry
RequireExpirationTime = true,
ValidateLifetime = true,
// Save token
SaveSigninToken = true
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Mvc", policy =>
{
policy.AuthenticationSchemes.Add(OpenIdConnectDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
});
}
More details here: https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.1