5

Hello,

In my ASP.NET Core application I'm using an OpenIdConnectServer for Api authentication. Everything works fine.

But there is one thing I cannot resolve - how to set custom folder for persisting token signing keys?

In service configuration I have:

services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"keys/"));

After first run, an application key is created there. But the OpenIdServer manages the keys somehow by itself.

app.UseOpenIdConnectServer(options => {
    ...
    options.DataProtectionProvider = app.ApplicationServices.GetDataProtectionProvider();
    ...
});

Despite that, the credentials signing key is created in default location:

 A new RSA key ... persisted on the disk: /home/.../.aspnet/aspnet-contrib/oidc-server/<some guid>.key.

Is that bug or a feature? How can I force the server to store the keys also in the keys/ folder?


Abstract - why I'm doing this:

My idea is to build an API from n docker images of this, hide it behind an load ballancer and run somewhere in the cloud. The problem is - when every instance in docker creates it's own application&signing key, the encrypted auth token will not work for any other instance except the one, that has created and signed the token with it's key. Therefore, I'm trying to distribute the same keys to every docker image running. To an pre-defined application folder, if possible.

Or is there any better approach or best practice?


Thanks you in advance.

Kévin Chalet
  • 39,509
  • 7
  • 121
  • 131
rudolfdobias
  • 1,778
  • 3
  • 17
  • 40
  • FYI, the OIDC server middleware doesn't change the way DataProtection keys are managed, but it's not the only keys it uses as there are actually 2 separate serialization mechanisms, as described in http://stackoverflow.com/questions/38541772/authorize-via-jwt-token/38542062. The debug message you're seeing is logged by the internal RSA key generation feature, that creates asymmetric keys for id_token signing. Note that this feature was mainly for development purposes and will be removed in the next beta (beta7). – Kévin Chalet Oct 09 '16 at 08:12

1 Answers1

5

Well, I figured it out.

First, we have to generate a x509 certificate (with private key) as described here

openssl genrsa -out private.key 1024
openssl req -new -x509 -key private.key -out publickey.cer -days 365
openssl pkcs12 -export -out certificate.pfx -inkey private.key -in publickey.cer

Copy it to the folder you like, key/certificate.pfx in this case.

Then, gently insert your new certificate to OpenIdConnectServer:

appsettings.json

"Keys": {
    "CertificatePath": "keys/certificate.pfx",
    "CertificatePassword": "<password you provider>"
}

Startup.cs

private X509Certificate2 CreateOauthCertificate(){
        var path = Configuration["Keys:CertificatePath"];
        var password = Configuration["Keys:CertificatePassword"];
        return new X509Certificate2(path, password);
    }

Starup.cs - Configure

app.UseOpenIdConnectServer(
    ...
    options.SigningCredentials.AddCertificate(CreateOauthCertificate());
    ...
});

Now I'm curious if there is a better way or not.

But this works.

Regards

Community
  • 1
  • 1
rudolfdobias
  • 1,778
  • 3
  • 17
  • 40
  • I have wondered a point. If you store `CertificatePath` and `CertificatePassword` into environment variables(or store with using secret manager tool) instead of `appsettings.json`, doesn't it work as expected? – adem caglin Oct 09 '16 at 06:02
  • This is exactly the right thing to do (it will even become mandatory with beta7, since the RSA key generation feature will be removed). – Kévin Chalet Oct 09 '16 at 08:15
  • @ademcaglin I suppose this should work too. I choosed json approach for clear demonstration here. – rudolfdobias Oct 09 '16 at 10:36
  • Thanks @rudolfdobias . I just wanted to learn is there a special reason of using appsettings(i have wondered if it is a docker specific case). – adem caglin Oct 09 '16 at 10:56
  • @ademcaglin In this case - I'm loading configuration files along with keys from AWS S3 in CI build time. The certificate is stored in some binary format and I couldn't put in env variable anyway. And there are lots of settings in the json for defining it in envs. Better approach could be connecting to S3 directly from application startup via AWSSDK.S3 filesystem. – rudolfdobias Oct 09 '16 at 15:32