Private Key error in Saml2Configuration.SigningCertificate with Self-Signed Cert - itfoxtec-identity-saml2

I would like to test this implementation using self-signed certificates. I'm using the MVC implementation and am running into The remote server returned an error: (500) Internal Server Error.
Debugging shows the error occurs in Saml2SignedXml.ComputeSignature(...) at line 36: ComputeSignature(), which is inherited from Microsoft's SignedMxl and I can't step into it.
Saml2Configuration.SigningCertificate shows HasPrivateKey = true, but an error for the PrivateKey property: Saml2Configuration.SigningCertificate.PrivateKey threw an exception of type System.NotSupportedException.
I see the private key in the same property when using the provide ITFoxtec cert.
I am using a self-signed cert because the tfoxtec.identity.saml2.testidpcore_Certificate.pfx cert causes a Incorrect URI format error in MVC.
Honestly, I don't think this is a code problem so much as a certificate problem, but I'm not sure where to look at this point.

You probably need to use another self-signed certificate.
It is possible to create at self-signed certificate in .NET core or .NET 5.0 like this:
/// <summary>
/// Create self-signed certificate with subject name. .
/// </summary>
/// <param name="subjectName">Certificate subject name, example: "CN=my-certificate, O=some-organisation".</param>
/// <param name="expiry">Certificate expiry, default 365 days.</param>
public static Task<X509Certificate2> CreateSelfSignedCertificateAsync(this string subjectName, TimeSpan? expiry = null)
{
using (var rsa = RSA.Create(2048))
{
var certRequest = new CertificateRequest(subjectName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
certRequest.CertificateExtensions.Add(
new X509BasicConstraintsExtension(false, false, 0, false));
certRequest.CertificateExtensions.Add(
new X509SubjectKeyIdentifierExtension(certRequest.PublicKey, false));
certRequest.CertificateExtensions.Add(
new X509KeyUsageExtension(
X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyAgreement,
false));
var now = DateTimeOffset.UtcNow;
return Task.FromResult(certRequest.CreateSelfSigned(now.AddDays(-1), now.Add(expiry ?? TimeSpan.FromDays(365))));
}
}
The code is from ITfoxtec.Identity X509Certificate2Extensions.cs and the code is e.g. used in FoxIDs.

Related

#AfterReturning from ExceptionHandler not working

I have a GlobalExceptionHandler class which contain multiple methods annotated with #ExceptionHandler.
#ExceptionHandler({ AccessDeniedException.class })
public final ResponseEntity<Object> handleAccessDeniedException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>(
"Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}
I have a AOP which is suppose to be triggered after the exception handler returns response.
#AfterReturning(value="#annotation(exceptionHandler)",returning="response")
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
//do something
}
But the #AfterReturning is not triggered after the handler returns a valid response.
Tried full qualified name but not working
#AfterReturning(value = "#annotation(org.springframework.web.bind.annotation.ExceptionHandler)", returning = "response"){
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
//do something
}
Please go through the documentation to understand the proxying mechanisms in Spring framework.
Assuming the ExceptionHandler code written was of the following format
#ControllerAdvice
public class TestControllerAdvice {
#ExceptionHandler({ AccessDeniedException.class })
final public ResponseEntity<Object> handleAccessDeniedException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>(
"Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}
}
key points from the documentation pertaining to the question are
Spring AOP uses either JDK dynamic proxies or CGLIB to create the
proxy for a given target object.
If the target object to be proxied implements at least one
interface, a JDK dynamic proxy is used. All of the interfaces
implemented by the target type are proxied. If the target object
does not implement any interfaces, a CGLIB proxy is created.
With CGLIB, final methods cannot be advised, as they cannot be overridden in runtime-generated subclasses.
OP identified the issue based on the comments and hints , this answer is for any future references.

WPF and EntityFrameworkCore - Adding migration gives "No database provider has been configured for this DbContext"

Note I have read the large number of SO answers that appear to be similar, but I am already doing what they suggested, so I don't know if there is some difference with WPF (they all seem to relate to ASP.NET). Also, most answers relate to run-time errors, not ones when adding migrations.
I'm trying to set up a .NET Core 3 WPF project that uses EntityFrameWork Core, but am having problems adding a migration. I have set up my context as follows...
public class ApplicationDbContext : DbContext {
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) {
}
public ApplicationDbContext() {
}
public DbSet<Product> Products { get; set; }
}
The parameterless constructor is there, as without it I get an exception Unable to create an object of type 'ApplicationDbContext' when trying to add a migration.
My App.xaml.cs contains the following...
public partial class App {
public IServiceProvider ServiceProvider { get; private set; }
public IConfiguration Configuration { get; private set; }
protected override void OnStartup(StartupEventArgs e) {
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appSettings.json", optional: false, reloadOnChange: true);
Configuration = builder.Build();
ServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
ServiceProvider = serviceCollection.BuildServiceProvider();
MainWindow mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
mainWindow.Show();
}
private void ConfigureServices(IServiceCollection services) {
// Configuration
services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));
// Database
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SqlConnection")));
// Windows
services.AddTransient(typeof(MainWindow));
}
}
I realise that some of this is irrelevant, but thought I'd show the whole class in case it reveals something I missed. The code is based on this blog post.
However, when I try to add a migration, I get an exception "No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext."
As far as I can see, I have configured the database provider. I put a breakpoint in the ConfigureServices method, and can see that services.AddDbContext is called with the correct connection string.
Anyone any ideas what I've missed?
UPDATE I tried connecting to an existing database, and it worked absolutely fine, so it looks like the database provider has been configured correctly. It's only when I try to add a migration that I get the exception.
UPDATE 2 It seems that the migration tool is using the parameterless constructor on the context, which is why it thinks the provider hasn't been configured. If I remove the lines that configure it from App.xaml.cs, and instead override the OnConfiguringmethod to call UseSqlServer then the migration works fine. However, apart from the fact that I've not seen anyone else doing this (which makes me wonder if it's really the right way to do it), I don't see how to get the connection string from the config file. I can't inject an IConfiguration parameter, as the whole issue is that migrations requires a parameterless constructor.
It's actually quite simple with .Net Core 3.1 and EF Core Version 5, Entity Framework will look at the entry point class for the static function CreateHostBuilder, in my case that would be the App class in app.xaml.cs.
Not entirely sure the convention required prior to .Net Core 3.1. From my experience it had something to do with having a Startup class with .Net Core 2.1 and ASP.Net.
https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli
My solution:
public partial class App : Application
{
/// <summary>
/// Necessary for EF core to be able to find and construct
/// the DB context.
/// </summary>
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
// Configure Application services
.ConfigureServices((context, services) =>
{
ConfigureServices(context, services);
});
}
/// <summary>
/// Not necessary but I prefer having a separate function for
/// configuring services.
/// </summary>
private static void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
...
}
/// <summary>
/// Hold the built Host for starting and stopping
/// </summary>
private readonly IHost AppHost;
/// <summary>
/// Constructor
/// </summary>
public App()
{
// Create Application host
AppHost = CreateHostBuilder(new string[] { }).Build();
}
/// <summary>
/// App Startup Event Handler
/// </summary>
private async void Application_Startup(object sender, StartupEventArgs e)
{
// Start the application host
await AppHost.StartAsync();
...
}
/// <summary>
/// App Exit Event Handler
/// </summary>
private async void Application_Exit(object sender, ExitEventArgs e)
{
// Kill the application host gracefully
await AppHost.StopAsync(TimeSpan.FromSeconds(5));
// Dispose of the host at the end of execution
AppHost.Dispose();
}
}
You need to implement IDesignTimeDbContextFactory. There is a lot of hidden plumbing in an ASP.NET Core app that deals with wiring up the apps service provider so it can be found by the dotnet ef tooling, but no such plumbing exists in WPF. In addition the ef tools know nothing about WPF events so your OnStartup method isn't going to even be called (an instance the class wont even get created) to create your DI setup so that the ef tools can find your DBContext.
Move the code that creates the ServiceProvider into the constructor, other than the bit that looks up the main window and displays it.
Implement IDesignTimeDbContextFactory<ApplicationDbContext>. In the implemented CreateDbContext method return ServiceProvider.GetRequiredService<ApplicationDbContext>()
The tooling will then create an instance of your class, which will setup DI, and call that method to get your (now configured) DB Context and it should work.
I'd also recommend moving to HostBuilder based config (that blog post was written before the final version of Core 3 was released). You will find an updated version of the same post here

Caching issuer and keys from the metadata endpoint

I followed the sample for calling an ASP.NET Web API from an ASP.NET Web App using the Azure AD B2C:
https://github.com/Azure-Samples/active-directory-b2c-dotnet-webapp-and-webapi
I've a question regarding the OpenIdConnectCachingSecurityTokenProvider
// This class is necessary because the OAuthBearer Middleware does not leverage
// the OpenID Connect metadata endpoint exposed by the STS by default.
public class OpenIdConnectCachingSecurityTokenProvider : IIssuerSecurityKeyProvider
{
public ConfigurationManager<OpenIdConnectConfiguration> _configManager;
private string _issuer;
private IEnumerable<SecurityKey> _keys;
private readonly string _metadataEndpoint;
private readonly ReaderWriterLockSlim _synclock = new ReaderWriterLockSlim();
public OpenIdConnectCachingSecurityTokenProvider(string metadataEndpoint)
{
_metadataEndpoint = metadataEndpoint;
_configManager = new ConfigurationManager<OpenIdConnectConfiguration>(metadataEndpoint, new OpenIdConnectConfigurationRetriever());
RetrieveMetadata();
}
/// <summary>
/// Gets the issuer the credentials are for.
/// </summary>
/// <value>
/// The issuer the credentials are for.
/// </value>
public string Issuer
{
get
{
RetrieveMetadata();
_synclock.EnterReadLock();
try
{
return _issuer;
}
finally
{
_synclock.ExitReadLock();
}
}
}
/// <summary>
/// Gets all known security keys.
/// </summary>
/// <value>
/// All known security keys.
/// </value>
public IEnumerable<SecurityKey> SecurityKeys
{
get
{
RetrieveMetadata();
_synclock.EnterReadLock();
try
{
return _keys;
}
finally
{
_synclock.ExitReadLock();
}
}
}
private void RetrieveMetadata()
{
_synclock.EnterWriteLock();
try
{
OpenIdConnectConfiguration config = Task.Run(_configManager.GetConfigurationAsync).Result;
_issuer = config.Issuer;
_keys = config.SigningKeys;
}
finally
{
_synclock.ExitWriteLock();
}
}
}
The metadata endpoint:
https://login.microsoftonline.com/{TENANT}.onmicrosoft.com/v2.0/.well-known/openid-configuration?p={POLICY}
Why all the time we need to make a call to retrieve the keys and the issuer?
Can I cache these values?
If yes, what's the best setting for the expiration?
Why all the time we need to make a call to retrieve the keys and the
issuer?
Signing key: Your app must use this signing key(public key) to validate the token which is signed by AAD using its private key. This metadata endpoint contains all the public key information in use at the particular moment:
https://login.microsoftonline.com/<yourtenantdomain>/discovery/v2.0/keys?p=<SigninPolicyName>
Issuer : Your application needs Issuer to validate the token's iss claim to trust this token. Issuer can be also retrieved from the OpenID connect metadata endpoint:
https://login.microsoftonline.com/<YourTenantDomain>/v2.0/.well-known/openid-configuration?p=<SigninPolicyName>
Identifies the security token service (STS) that constructs and
returns the token. In the tokens that Azure AD returns, the issuer is
sts.windows.net. The GUID in the Issuer claim value is the tenant ID
of the Azure AD directory. The tenant ID is an immutable and reliable
identifier of the directory.
Also,OAuthBearer Middleware doesn't leverage this metadata endpoint by default, so you need to retrieve it with code. So, you must retrieve the keys and the issuer to validate the token.
Can I cache these values? If yes, what's the best setting for the
expiration?
Yes, with the code you post, it cache these values in configManager.GetConfigurationAsync and OpenIdConnectCachingSecurityTokenProvider use it when starting up.
About the expiration: Signing key can roll over. So, don't worry about the set expiration for the singing key. The important thing is that you'd better to fetch the metadata location dynamically to keep the signing key is the correct.
Reference:
You can see the details about Validate the signature of B2C tokens in this documentaion.
See more details about Signing key rollover in AAD in this documentation.
See more details about OpendID Provider Metadata :http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata

Change the connection string of nopCommerce?

I am using nopCommerce and I need to remove the connection string in the settings.txt file and insert the web.config file. How can i do this?
The most straightforward way to move the connection string out of settings.txt and into the web.config is to modify the Nop.Core.Data.DataSettingsManager. Specifically the LoadSettings() and SaveSettings() methods. You can store the connection string wherever you'd like (ideally in web.config), as long as those two methods read and write the configuration.
A rough example of the DataSettingsManager updated to support storing the connection string in web.config can be found in this Gist: http://git.io/vUPcI Just copy the connection string from settings.txt to web.config and name the connection "DefaultConnection" or adapt the code accordingly.
Just do two steps
Replace two method LoadSettings and SaveSettings in \nopCommerce\Libraries\Nop.Core\Data\DataSettingsManager.cs. Code from link of #Stephen Kiningham
/// <summary>
/// Load settings
/// </summary>
/// <param name="filePath">File path; pass null to use default settings file path</param>
/// <returns></returns>
public virtual DataSettings LoadSettings(string filePath = null)
{
try
{
System.Configuration.Configuration webConfig = WebConfigurationManager.OpenWebConfiguration(HttpRuntime.AppDomainAppVirtualPath);
return new DataSettings
{
DataConnectionString = webConfig.ConnectionStrings.ConnectionStrings["DefaultConnection"].ConnectionString,
DataProvider = webConfig.ConnectionStrings.ConnectionStrings["DefaultConnection"].ProviderName
};
}
catch (NullReferenceException)
{
return new DataSettings();
}
}
/// <summary>
/// Save settings to a file
/// </summary>
/// <param name="settings"></param>
public virtual void SaveSettings(DataSettings settings)
{
if (null == settings) throw new ArgumentNullException("settings");
System.Configuration.Configuration webConfig = WebConfigurationManager.OpenWebConfiguration(HttpRuntime.AppDomainAppVirtualPath);
webConfig.ConnectionStrings.ConnectionStrings["DefaultConnection"].ConnectionString = settings.DataConnectionString;
webConfig.ConnectionStrings.ConnectionStrings["DefaultConnection"].ProviderName = settings.DataProvider;
webConfig.Save();
}
Add connection string to your web config web.config
<connectionStrings>
<add name="DefaultConnection"
connectionString=" Data Source=localhost;Initial Catalog=nopcommerce;Integrated Security=True;Persist Security Info=False"
providerName="sqlserver">
</add>
</connectionStrings>
[1] In .NET Core (3.1 | NopCommerce 4.3) I created various appsettings.json files (including appsettings.json, appsettings.Development.json, appsettings.Integration.json, appsettings.Staging.json) and logic (beyond this discuss) determines the the correct settings to be used in the proper environment etc.
[2] \nopCommerce\Libraries\Nop.Core\Data\DataSettingsManager.cs
I created the following method:
public static string GetConnectionString()
{
var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
string appSettingsFileName = env switch
{
"Development" => "appsettings.Development.json",
"Production" => "appsettings.json",
"Staging" => "appsettings.Staging.json",
"Integration" => "appsettings.Integration.json",
_ => "appsettings.json",
};
IConfigurationRoot configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile(appSettingsFileName).Build();
string connectionString = configuration.GetConnectionString("DefaultConnection");
return connectionString;
}
(returns the proper connection string for the proper environment)
[3] In LoadSettings -- I didn't change anything to get down to the line
Singleton<DataSettings>.Instance = JsonConvert.DeserializeObject<DataSettings>(text);
... I just added a new line below to replace the .ConnectionString with the connectionstring determined from our new method:
Singleton<DataSettings>.Instance.ConnectionString = GetConnectionString();
important:
When I ran it there were three or four places where there was a switch (case > default:) that was looking for a provider etc -- But I just copied the settings from MsSql down to the default: and it worked fine. I know this is sloppy but I am never using MySql for this project and so far as I am concerned its a non-issue. Either way - I broke it to make it work (multiple Azure App environments are more important).
I suggest they should have built it the regular way and just provided us with a SQL script for deployment (over engineered a non-issue?) since we usually have to do that anyway for custom development (seems silly to me to hard code a data settings file in App_Data) - but I trust their logic.
Please add this to your web.config under Nop.Web project :
<connectionStrings>
<add name="MyConnectionString"
connectionString="Data Source=serverName;Initial Catalog=DBName;Persist Security Info=False;UserID=userName;Password=password"
</connectionStrings>
Best Regards.
In addition to adding the connection to the web.config, you have to specify the providerName="sqlserver".
Ex) ;Initial Catalog=;Integrated
Security=False;User ID=;Password=;Connect
Timeout=30;Encrypt=True"
providerName="sqlserver" />
This is because the EfDataProviderManager in Nop.Data has a check for the provider name, and will throw an exception if you put the normal
providerName="System.Data.SqlClient"

Inheritance security rules violated while overriding member in Silverlight

I am working on a web application in silverlight. I have overloaded the WebClient.GetWebRequest method as given below:-
public class WebClientWithCookies : WebClient
{
[SecurityCritical]
protected override WebRequest GetWebRequest(Uri address)
{
string cookieContent = HtmlPage.Document.Cookies;
WebRequest request = base.GetWebRequest(address);
HttpWebRequest webRequest = request as HttpWebRequest;
if (webRequest != null && cookieContent != null && cookieContent != string.Empty)
{
CookieContainer cookieContainer = new CookieContainer();
cookieContainer.Add(address, new Cookie() { Value = HtmlPage.Document.Cookies });
webRequest.CookieContainer = cookieContainer;
}
return request;
}
}
But I am getting the following exception:
System.TypeInitializationException was unhandled by user code
Message=The type initializer for 'SigmaWC.Utility.RestCommunicator'
threw an exception. TypeName=SigmaWC.Utility.RestCommunicator
StackTrace:
at SigmaWC.Utility.RestCommunicator..ctor()
at SigmaWC.App..ctor() InnerException: System.TypeLoadException
Message=Inheritance security rules violated while overriding member: 'SigmaWC.Utility.WebClientWithCookies..ctor()'. Security
accessibility of the overriding method must match the security
accessibility of the method being overriden.
StackTrace:
at SigmaWC.Utility.RestCommunicator..cctor()
InnerException:
Can anyone help in how to elevate the security settings in silverlight.
Documentation about this is scarce to say the least. However, there are a couple of resources which are useful:
MSDN Indicates that you cannot use framework members with a SecurityCriticalAttribute.
Types and members that have the SecurityCriticalAttribute cannot be used by Silverlight application code. Security-critical types and members can be used only by trusted code in the .NET Framework for Silverlight class library.
In the case of WebClient, the GetWebRequest method does not have this attribute, however the constructor does.
This MSDN Security blog Implies that if the default constructor has any Security attribute, the class cannot be used for inheritance in a Silverlight client.
Further to that, the aforementioned MSDN blog implies that Security attributes are ignored in Silverlight assemblies which are not part of the core framework. This may however only apply to Assembly level attributes.
Anyway, to cut a long story short. You cannot derive from WebClient because of the SecuritySafeAttribute on the constructor.
To illustrate the point, this also causes an exception at runtime:
public class MyWebClient : WebClient
{
}
The alternative is to roll your own WebClient. It takes a little work, but the following example does work with the following handler:
public class MyHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
foreach (Cookie cookie in context.Response.Cookies)
{
//Cookies from the client - there will be 1 in this case
}
}
...
public class MyWebClient
{
public MyWebClient()
{
}
public void InvokeWebRequest(Uri address)
{
//Set the cookie you want to use.
string cookieContent = "I like cookies";
// Register a http client - without this the following webRequest.CookieContainer setter will throw an exception
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
//This bit you know, but dont forget to set Name on your new Cookie.
HttpWebRequest webRequest = WebRequest.Create(address.AbsoluteUri) as HttpWebRequest;
if (webRequest != null && !String.IsNullOrWhiteSpace(cookieContent))
{
webRequest.CookieContainer = new CookieContainer();
webRequest.CookieContainer.Add(address, new Cookie() { Value = cookieContent, Name = "MyCookie" });
}
//Invoke the async GetResponse method.
webRequest.BeginGetResponse(o =>
{
HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(o);
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
//Read the result
string result = reader.ReadToEnd();
}
foreach (Cookie cookie in response.Cookies)
{
//The cookies returned from the server.
}
}, null);
}
}

Resources