# 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 authorization 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));

    File.WriteAllBytes("encryption-certificate.pfx", 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));

    File.WriteAllBytes("signing-certificate.pfx", certificate.Export(X509ContentType.Pfx, string.Empty));

The best place to store your certificates will 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 Use a TLS/SSL certificate in your code in Azure App Service.

## Importing credentials in the API/resource 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");
        });