ComponentSpace

Forums



encrypt password for "LocalCertificates" section in JSON SAML file


encrypt password for "LocalCertificates" section in JSON SAML file

Author
Message
eric_08
eric_08
New Member
New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)

Group: Awaiting Activation
Posts: 7, Visits: 42
I have separate SAML JSON file for storing SAML configuration settings. I'm trying to implement service provider side, but one of my requirements is that the "Password" value used for PFX file for service provider certificate needs to be encrypted. I looked at this in detail, and I came up with my CustomSamlConfigurationResolver class that extends built-in SamlConfigurationResolver class. The code looks like this: (The assumption here is that passwords are already encrypted, which is done by separate code)

public class CustomSamlConfigurationResolver : SamlConfigurationResolver
  {
   private readonly Lazy<IDataProtector> protector;

   private bool isUnprotected;

   public CustomSamlConfigurationResolver(IDataProtectionProvider dataProtectionProvider, IOptionsSnapshot<SamlConfigurations> samlConfigurations)
    : base(samlConfigurations)
   {
    this.protector = new Lazy<IDataProtector>(() => dataProtectionProvider.CreateProtector("Certs"));
   }

   public override Task<LocalServiceProviderConfiguration> GetLocalServiceProviderConfigurationAsync(string configurationID)
   {
    var task = base.GetLocalServiceProviderConfigurationAsync(configurationID);

    if (this.isUnprotected)
    {
      return task;
    }

    var localServiceProviderConfiguration = task.Result;

    this.isUnprotected = true;
    foreach (var certificate in localServiceProviderConfiguration.LocalCertificates)
    {
      if (!string.IsNullOrWhiteSpace(certificate.Password))
      {
       certificate.Password = this.protector.Value.Unprotect(certificate.Password);
      }
    }

    return task;
   }

The above class is registered in Startup class like this:

   services.TryAddScoped<ISamlConfigurationResolver, CustomSamlConfigurationResolver>();
    services.AddSaml(this.Configuration.GetSection("SAML"));

Everything seems to work, but I'd like to know if there is easier way to accomplish this.

Thanks,
Eric
ComponentSpace
ComponentSpace
ComponentSpace Development
ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)

Group: Administrators
Posts: 3.2K, Visits: 11K
Hi Eric,
That looks good to me.
One alternative is to implement the ICertificateLoader interface instead of extending the SamlConfigurationResolver.
You would do this by extending the CertificateLoader class and overriding the LoadCertificateFromFileAsync method.
For example:


public override Task<X509Certificate2> LoadCertificateFromFileAsync(string certificateFile, string certificatePassword)
{
    if (!string.IsNullOrEmpty(certificatePassword))
    {
        certificatePassword= this.protector.Value.Unprotect(certificatePassword);
    }

    return LoadCertificateFromFileAsync(certificateFile, certificatePassword);
}



This class and the interface are under the ComponentSpace.Saml2.Certificates namespace.



Regards
ComponentSpace Development
eric_08
eric_08
New Member
New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)

Group: Awaiting Activation
Posts: 7, Visits: 42
ComponentSpace - 8/15/2019
Hi Eric,
That looks good to me.
One alternative is to implement the ICertificateLoader interface instead of extending the SamlConfigurationResolver.
You would do this by extending the CertificateLoader class and overriding the LoadCertificateFromFileAsync method.
For example:


public override Task<X509Certificate2> LoadCertificateFromFileAsync(string certificateFile, string certificatePassword)
{
    if (!string.IsNullOrEmpty(certificatePassword))
    {
        certificatePassword= this.protector.Value.Unprotect(certificatePassword);
    }

    return LoadCertificateFromFileAsync(certificateFile, certificatePassword);
}



This class and the interface are under the ComponentSpace.Saml2.Certificates namespace.


Thanks you a quick reply. I implemented your suggestion, and it does look better and cleaner. I basically extended CertificateLoader class and did override on LoadCertificateFromFileAsync() and LoadCertificateFromStringAsync() methods. I also registered the new class with TryAddTransient() method. Everything looks good, but I do have one question. Do I have to create my own CachedCertificateLoader class as well? In the default CachedCertificateLoader class, it initializes standard CertificateLoader class, so I'm thinking I will need to have custom CachedCertificateLoader class where it initializes my custom CertificateLoader class. Is this correct?

Thanks,
Eric
ComponentSpace
ComponentSpace
ComponentSpace Development
ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)

Group: Administrators
Posts: 3.2K, Visits: 11K
That's correct. Of course, caching certificates is optional but if you wish to with your custom certificate loader you need to provide a custom cached certificate loader that uses the custom certificate loader.

The easiest way to do this is to extend the AbstractCachedCertificateLoader and specify your custom certificate loader. For example:


public class CustomCertificateLoader : CertificateLoader
{
  public CustomCertificateLoader(IConfiguration configuration, ILoggerFactory loggerFactory)
   : base(configuration, loggerFactory)
  {
  }

  public override Task<X509Certificate2> LoadCertificateFromFileAsync(string certificateFile, string certificatePassword)
  {
   if (!string.IsNullOrEmpty(certificatePassword))
   {
      certificatePassword = this.protector.Value.Unprotect(certificatePassword);
   }

   return LoadCertificateFromFileAsync(certificateFile, certificatePassword);
  }
}

public class CustomCachedCertificateLoader : AbstractCachedCertificateLoader
{
  public CustomCachedCertificateLoader(
   IConfiguration configuration,
   IOptionsSnapshot<CertificateCacheOptions> certificateCacheOptions,
   IDistributedCache distributedCache,
   ILoggerFactory loggerFactory)
   : base(new CustomCertificateLoader(configuration, loggerFactory), certificateCacheOptions, distributedCache, loggerFactory)
  {
  }
}



Register the CustomCachedCertificateLoader with TryAddTransient().

Regards
ComponentSpace Development
eric_08
eric_08
New Member
New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)New Member (10 reputation)

Group: Awaiting Activation
Posts: 7, Visits: 42
ComponentSpace - 8/16/2019
That's correct. Of course, caching certificates is optional but if you wish to with your custom certificate loader you need to provide a custom cached certificate loader that uses the custom certificate loader.

The easiest way to do this is to extend the AbstractCachedCertificateLoader and specify your custom certificate loader. For example:


public class CustomCertificateLoader : CertificateLoader
{
  public CustomCertificateLoader(IConfiguration configuration, ILoggerFactory loggerFactory)
   : base(configuration, loggerFactory)
  {
  }

  public override Task<X509Certificate2> LoadCertificateFromFileAsync(string certificateFile, string certificatePassword)
  {
   if (!string.IsNullOrEmpty(certificatePassword))
   {
      certificatePassword = this.protector.Value.Unprotect(certificatePassword);
   }

   return LoadCertificateFromFileAsync(certificateFile, certificatePassword);
  }
}

public class CustomCachedCertificateLoader : AbstractCachedCertificateLoader
{
  public CustomCachedCertificateLoader(
   IConfiguration configuration,
   IOptionsSnapshot<CertificateCacheOptions> certificateCacheOptions,
   IDistributedCache distributedCache,
   ILoggerFactory loggerFactory)
   : base(new CustomCertificateLoader(configuration, loggerFactory), certificateCacheOptions, distributedCache, loggerFactory)
  {
  }
}



Register the CustomCachedCertificateLoader with TryAddTransient().

That's exactly what I did. Thanks a reply!
ComponentSpace
ComponentSpace
ComponentSpace Development
ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)ComponentSpace Development (4.4K reputation)

Group: Administrators
Posts: 3.2K, Visits: 11K
You're welcome.

Regards
ComponentSpace Development
GO


Similar Topics


Execution: 0.000. 1 query. Compression Enabled.
Login
Existing Account
Email Address:


Password:


Select a Forum....












Forums, Documentation & Knowledge Base - ComponentSpace


Search