Ed M.
Ed M.

Reputation: 31

WindowsCryptographicException: Access is denied when publishing app in Azure

I have a very simple Web App based on the Aridka OpenIddict sample, pretty much a copy of it when it comes to the Authorization controller and the startup class, with some differences with regards to the type of resource that is returned, but the token mechanism is exactly as per the sample.

The App works well in my dev environment (the db is in Azure, but the app runs in my machine). However, I have published it to Azure just to see if it still worked once hosted in the cloud provider and it actually returns an error and does not start. This is the stack trace:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Access is denied.
   at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags)
   at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags)
   at Microsoft.Extensions.DependencyInjection.OpenIddictServerBuilder.AddDevelopmentEncryptionCertificate(X500DistinguishedName subject)
   at Microsoft.Extensions.DependencyInjection.OpenIddictServerBuilder.AddDevelopmentEncryptionCertificate()
   at MyApp.Api.Startup.<>c.<ConfigureServices>b__4_4(OpenIddictServerBuilder options) in C:\Users\edm\OneDrive\MyAp\1\1\MyApp.Api\Startup.cs:line 75
   at Microsoft.Extensions.DependencyInjection.OpenIddictServerExtensions.AddServer(OpenIddictBuilder builder, Action`1 configuration)
   at MyApp.Api.Startup.ConfigureServices(IServiceCollection services) in C:\Users\edm\OneDrive\MyApp\1\1\MyApp.Api\Startup.cs:line 54
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.InvokeCore(Object instance, IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass9_0.<Invoke>g__Startup|0(IServiceCollection serviceCollection)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.Invoke(Object instance, IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass8_0.<Build>b__0(IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.UseStartup(Type startupType, HostBuilderContext context, IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass12_0.<UseStartup>b__0(HostBuilderContext context, IServiceCollection services)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at MyApp.Api.Program.Main(String[] args) in C:\Users\edm\OneDrive\MyApp\1\1\MyApp.Api\Program.cs:line 16

I really appreciate any help. I am new to OpenId so if it's too basic a question and there are other resources I should read first, do not hesitate to share references.

Thank you!

Ed

Upvotes: 1

Views: 4704

Answers (2)

Ed M.
Ed M.

Reputation: 31

Thanks a lot for all the references. I have continued to investigate. In [the link I shared previously][1], Kevin Chalet, the lead contributor of OpenIddict made an explicit mention to not use the sample code when it comes to certificates and suggested to create our own.

So I learned how to create self-signed certificates with Powershell thanks to a Troy Hunt course in Pluralsight. Funny that Jason was pointing me in the same direction in his comment (@Jason, thanks a lot, I cannot upvote you yet as I don't have enough reputation/points, but I will when I am allowed).

Here is how to do it, for reference:

PS> New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname example.mysite.com

When executing this it will output the thumprint and the subject of our certificate.

PS> $pwd = ConvertTo-SecureString -String "WHATEVERPASSWORDYOUWANT" -Force -AsPlainText

You define the $pwd variable that we will use to export the certificate with this command:

PS> Export-PfxCertificate -cert cert:\localMachine\my\THE_THUMBPRINT_YOU_GOT_EARLIER -FilePath "YOUR_PATH\cert.pfx" -Password $pwd

Then I could upload this certificate to App Service as Jason replied above, and then in my code I had to change my Startup class by changing the default

options.AddDevelopmentEncryptionCertificate().AddDevelopmentSigningCertificate();

to

options.AddEncryptionCertificate("THE_THUMBPRINT_YOU_GOT_EARLIER").AddSigningCertificate("THE_THUMBPRINT_YOU_GOT_EARLIER");

And the last thing to do was to add this application setting to the Azure App:

WEBSITE_LOAD_CERTIFICATES with the thumbprint from above as the value.

Note: in order to be able to upload the private certificate (pfx) into Azure you need to have at a minimum the Basic tier in your app service plan.

Thanks to all [1]: https://github.com/openiddict/openiddict-core/issues/976

Upvotes: 2

Jason Pan
Jason Pan

Reputation: 22019

  1. Add application setting WEBSITE_LOAD_USER_PROFILE=1 on portal.

    If not works, try the second method.

  2. Add CERTIFICATES to your web app.

    Upload certificate to App Service

Upvotes: 8

Related Questions