diff --git a/configuration/encryption-and-signing-credentials.html b/configuration/encryption-and-signing-credentials.html new file mode 100644 index 0000000..5770961 --- /dev/null +++ b/configuration/encryption-and-signing-credentials.html @@ -0,0 +1,229 @@ + + + + + + + + Encryption and signing credentials + + + + + + + + + + + + + + + +
+
+ +
+
+
+ + + + +
+
+
+
+ +
+
+
+
+
+ +
+
+
    +
  • +
+
+
+
+
+ +
+ Show / Hide Table of Contents +
+
+
+
+
+
+
+

Encryption and signing credentials

+ +

To protect the tokens it issues, OpenIddict uses 2 types of credentials:

+
    +
  • Signing credentials are used to protect against tampering. They can be either asymmetric (e.g a RSA or ECDSA key) or symmetric.
  • +
  • Encryption credentials are used to ensure the content of tokens cannot be read by malicious parties. They can be either asymmetric (e.g a RSA key) or symmetric.
  • +
+
Note

Tokens generated using the opt-in ASP.NET Core Data Protection integration rely on their own key ring, distinct from the credentials discussed in this documentation. +For more information about Data Protection, visit ASP.NET Core Data Protection.

+
+

Registering credentials in the server options

+

OpenIddict allows registering one or multiple keys (raw keys or embedded in X.509 certificates).

+
Note

When multiple keys/certificates are registered (which can be useful to implement keys rotation), OpenIddict chooses the most appropriate key based on the following algorithm:

+
    +
  • Symmetric keys are always chosen first, except for identity tokens, that can only be signed using asymmetric keys.
  • +
  • Asymmetric keys embedded in X.509 certificates are ordered based on the NotAfter and NotBefore dates (certificates that are not yet valid +are not used by OpenIddict and certificates with the furthest expiration date are always preferred).
  • +
  • X.509 certificates are always preferred to raw RSA/ECDSA keys.
  • +
+
+

Registering an ephemeral key

+

For development purposes, an ephemeral key - that is not persisted or shared across instances - can be used to sign or encrypt tokens:

+
services.AddOpenIddict()
+    .AddServer(options =>
+    {
+        options.AddEphemeralEncryptionKey()
+               .AddEphemeralSigningKey();
+    });
+
Note

options.AddEphemeralEncryptionKey() generates an asymmetric RSA key which is not directly used as-is to encrypt the tokens but is used to encrypt an +intermediate per-token symmetric key with which the token content is first encrypted using AES. +For more information about this mechanism, read Key Encryption with RSAES OAEP.

+
+

Registering a development certificate

+

For development purposes, a certificate can be generated and stored by OpenIddict in the certificates store of the user account running the OpenIddict server feature. +Unlike ephemeral keys, development certificates are persisted - but not shared across instances - and will be reused when the application host is restarted.

+
services.AddOpenIddict()
+    .AddServer(options =>
+    {
+        options.AddDevelopmentEncryptionCertificate()
+               .AddDevelopmentSigningCertificate();
+    });
+
Warning

This feature is not available on .NET Framework 4.6.1: calling options.AddDevelopmentEncryptionCertificate() or options.AddDevelopmentSigningCertificate() +will result in a PlatformNotSupportedException being thrown at runtime if no valid development certificate can be found and a new one must be generated.

+
+

Registering a key

+

To register a signing or encryption key, an instance of a SecurityKey - typically a SymmetricSecurityKey or a RsaSecurityKey - +can be provided to the options.AddSigningKey()/options.AddEncryptionKey() methods:

+
services.AddOpenIddict()
+    .AddServer(options =>
+    {
+        options.AddEncryptionKey(new SymmetricSecurityKey(
+            Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY=")));
+    });
+
Note

While signing keys can be either symmetric or asymmetric, OpenIddict requires registering at least one asymmetric key to sign identity tokens. +If both an asymmetric and a symmetric signing key are registered, the symmetric key will always be preferred when protecting access tokens, +authorization codes or refresh tokens, while the asymmetric key will be used to sign identity tokens, that are meant to be publicly validated.

+
+

Registering a certificate (recommended for production-ready scenarios)

+

To register a signing or encryption certificate, the options.AddSigningCertificate()/options.AddEncryptionCertificate() methods can be called +with an instance of X509Certificate2. Alternatively, a unique thumbprint identifying the certificate in the machine or user certificate store +of the operating system can also be provided.

+

In production, it is recommended to use two RSA certificates, distinct from the certificate(s) used for HTTPS: one for encryption, one for signing. +Certificates can be generated and self-signed locally using the .NET Core CertificateRequest API:

+
using var algorithm = RSA.Create(keySizeInBits: 2048);
+
+var subject = new X500DistinguishedName("CN=Fabrikam Encryption Certificate");
+var request = new CertificateRequest(subject, algorithm, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment, critical: true));
+
+var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(2));
+var data = certificate.Export(X509ContentType.Pfx, string.Empty);
+
using var algorithm = RSA.Create(keySizeInBits: 2048);
+
+var subject = new X500DistinguishedName("CN=Fabrikam Signing Certificate");
+var request = new CertificateRequest(subject, algorithm, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, critical: true));
+
+var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(2));
+var data = certificate.Export(X509ContentType.Pfx, string.Empty);
+

The best place to store your certificates will mostly depend on your host:

+
    +
  • For IIS applications, storing the certificates in the machine store is the recommended option.
  • +
  • On Azure, certificates can be uploaded and exposed to Azure App Services applications using the special WEBSITE_LOAD_CERTIFICATES flag. +For more information, visit https://docs.microsoft.com/en-us/azure/app-service/configure-ssl-certificate-in-code
  • +
+

Importing credentials in the validation options

+

Using the options.UseLocalServer() integration

+

When the API and the authorization server are part of the same project, both the signing and +encryption credentials can be easily imported by calling options.UseLocalServer():

+
services.AddOpenIddict()
+    .AddValidation(options =>
+    {
+        options.UseLocalServer();
+    });
+

Using OpenID Connect discovery (asymmetric signing keys only)

+

When the API and the authorization server are hosted in different applications, +standard OpenID Connect discovery can be used to automatically import asymmetric signing keys:

+
services.AddOpenIddict()
+    .AddValidation(options =>
+    {
+        options.SetIssuer("https://localhost:44319/");
+        options.UseSystemNetHttp();
+    });
+

Registering a symmetric signing key in the token validation parameters

+

Unlike asymmetric signing keys, symmetric keys - used with HMAC-based algorithms like HS256 - cannot +be safely exposed by an OpenID Connect discovery endpoint. As such, they can't be automatically imported by the OpenIddict validation handler. +For applications that require using a symmetric signing key, the advanced configuration APIs can be used to register it in the token validation options:

+
services.AddOpenIddict()
+    .AddValidation(options =>
+    {
+        options.Configure(options => options.TokenValidationParameters.IssuerSigningKey =
+            new SymmetricSecurityKey(
+                Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY=")));
+    });
+

Registering an encryption key or certificate

+

To import an encryption key/certificate, the same overloads as the ones exposed by the OpenIddict server feature can be used:

+
services.AddOpenIddict()
+    .AddValidation(options =>
+    {
+        options.AddEncryptionCertificate("b82f36609cdaff9a95de60e8d5ac774b2e496c4b");
+    });
+
+
+ +
+
+
+
    +
  • + Improve this Doc +
  • +
+
+
+
In This Article
+
+
+
+
+
+
+ +
+
+
+
+ + Back to top + + + Generated by DocFX +
+
+
+
+ + + + + + diff --git a/configuration/toc.html b/configuration/toc.html index a07188e..6945c49 100644 --- a/configuration/toc.html +++ b/configuration/toc.html @@ -24,6 +24,9 @@
  • Claim destinations
  • +
  • + Encryption and signing credentials +
  • Proof Key for Code Exchange
  • diff --git a/manifest.json b/manifest.json index a9d0312..c3424ea 100644 --- a/manifest.json +++ b/manifest.json @@ -5631,6 +5631,18 @@ "is_incremental": false, "version": "" }, + { + "type": "Conceptual", + "source_relative_path": "configuration/encryption-and-signing-credentials.md", + "output": { + ".html": { + "relative_path": "configuration/encryption-and-signing-credentials.html", + "hash": "22Qc2JwWKL314U4Wddl0IQ==" + } + }, + "is_incremental": false, + "version": "" + }, { "type": "Conceptual", "source_relative_path": "configuration/index.md", @@ -5661,7 +5673,7 @@ "output": { ".html": { "relative_path": "configuration/toc.html", - "hash": "hEZG047NIeu+o0KUdkadEA==" + "hash": "OsKSxgt/kroRjpQlAjf8PA==" } }, "is_incremental": false, @@ -7965,7 +7977,7 @@ "ConceptualDocumentProcessor": { "can_incremental": false, "incrementalPhase": "build", - "total_file_count": 130, + "total_file_count": 131, "skipped_file_count": 0 }, "ManagedReferenceDocumentProcessor": {