From e4b2150f23793c6a502f0c13b5bc4d691fe2f3bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Tue, 14 Jan 2020 20:44:33 +0100 Subject: [PATCH] Enforce JWT access token encryption by default --- samples/Mvc.Server/Startup.cs | 5 ++++ .../OpenIddictServerBuilder.cs | 9 +++++++ .../OpenIddictServerHandlers.cs | 27 ++++++++++++------- .../OpenIddictServerOptions.cs | 7 +++++ ...alidationServerIntegrationConfiguration.cs | 8 ++---- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/samples/Mvc.Server/Startup.cs b/samples/Mvc.Server/Startup.cs index 2214f34f..a3cf1adc 100644 --- a/samples/Mvc.Server/Startup.cs +++ b/samples/Mvc.Server/Startup.cs @@ -114,6 +114,11 @@ namespace Mvc.Server // options.IgnoreEndpointPermissions() // .IgnoreGrantTypePermissions() // .IgnoreScopePermissions(); + + // Note: when issuing access tokens used by third-party APIs + // you don't own, you can disable access token encryption: + // + // options.DisableAccessTokenEncryption(); }) // Register the OpenIddict validation components. diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs index 7d14462e..5ed437d1 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -1621,6 +1621,15 @@ namespace Microsoft.Extensions.DependencyInjection }); } + /// + /// Disables JWT access token encryption (this option doesn't affect Data Protection tokens). + /// Disabling encryption is NOT recommended and SHOULD only be done when issuing tokens + /// to third-party resource servers/APIs you don't control and don't fully trust. + /// + /// The . + public OpenIddictServerBuilder DisableAccessTokenEncryption() + => Configure(options => options.DisableAccessTokenEncryption = true); + /// /// Disables authorization storage so that ad-hoc authorizations are /// not created when an authorization code or refresh token is issued diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.cs index f505c7be..454bf95c 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.cs @@ -2729,12 +2729,13 @@ namespace OpenIddict.Server Subject = (ClaimsIdentity) principal.Identity }); - var credentials = context.Options.EncryptionCredentials.FirstOrDefault( - credentials => credentials.Key is SymmetricSecurityKey); - if (credentials != null) + if (!context.Options.DisableAccessTokenEncryption) { - token = context.Options.JsonWebTokenHandler.EncryptToken( - token, credentials, new Dictionary(StringComparer.Ordinal) + token = context.Options.JsonWebTokenHandler.EncryptToken(token, + context.Options.EncryptionCredentials.FirstOrDefault( + credentials => credentials.Key is SymmetricSecurityKey) ?? + context.Options.EncryptionCredentials.First(), + new Dictionary(StringComparer.Ordinal) { [JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.AccessToken }); @@ -2912,7 +2913,9 @@ namespace OpenIddict.Server // Sign and encrypt the authorization code. var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); token = context.Options.JsonWebTokenHandler.EncryptToken(token, - context.Options.EncryptionCredentials.First(), + context.Options.EncryptionCredentials.FirstOrDefault( + credentials => credentials.Key is SymmetricSecurityKey) ?? + context.Options.EncryptionCredentials.First(), new Dictionary(StringComparer.Ordinal) { [JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.AuthorizationCode @@ -3089,7 +3092,9 @@ namespace OpenIddict.Server // Sign and encrypt the device code. var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); token = context.Options.JsonWebTokenHandler.EncryptToken(token, - context.Options.EncryptionCredentials.First(), + context.Options.EncryptionCredentials.FirstOrDefault( + credentials => credentials.Key is SymmetricSecurityKey) ?? + context.Options.EncryptionCredentials.First(), new Dictionary(StringComparer.Ordinal) { [JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.DeviceCode @@ -3367,7 +3372,9 @@ namespace OpenIddict.Server // Sign and encrypt the refresh token. var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); token = context.Options.JsonWebTokenHandler.EncryptToken(token, - context.Options.EncryptionCredentials.First(), + context.Options.EncryptionCredentials.FirstOrDefault( + credentials => credentials.Key is SymmetricSecurityKey) ?? + context.Options.EncryptionCredentials.First(), new Dictionary(StringComparer.Ordinal) { [JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.RefreshToken @@ -3573,7 +3580,9 @@ namespace OpenIddict.Server }); token = context.Options.JsonWebTokenHandler.EncryptToken(token, - context.Options.EncryptionCredentials.First(), + context.Options.EncryptionCredentials.FirstOrDefault( + credentials => credentials.Key is SymmetricSecurityKey) ?? + context.Options.EncryptionCredentials.First(), new Dictionary(StringComparer.Ordinal) { [JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.UserCode diff --git a/src/OpenIddict.Server/OpenIddictServerOptions.cs b/src/OpenIddict.Server/OpenIddictServerOptions.cs index c8fdc0e5..867c7c31 100644 --- a/src/OpenIddict.Server/OpenIddictServerOptions.cs +++ b/src/OpenIddict.Server/OpenIddictServerOptions.cs @@ -218,6 +218,13 @@ namespace OpenIddict.Server OpenIddictConstants.Claims.Subject }; + /// + /// Gets or sets a boolean indicating whether access token encryption should be disabled. + /// Disabling encryption is NOT recommended and SHOULD only be done when issuing tokens + /// to third-party resource servers/APIs you don't control and don't fully trust. + /// + public bool DisableAccessTokenEncryption { get; set; } + /// /// Gets or sets a boolean indicating whether authorization storage should be disabled. /// When disabled, ad-hoc authorizations are not created when an authorization code or diff --git a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs index 9bb1db51..6734e55a 100644 --- a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs +++ b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs @@ -8,7 +8,6 @@ using System; using System.Linq; using JetBrains.Annotations; using Microsoft.Extensions.Options; -using Microsoft.IdentityModel.Tokens; using OpenIddict.Server; namespace OpenIddict.Validation.ServerIntegration @@ -48,13 +47,10 @@ namespace OpenIddict.Validation.ServerIntegration (from credentials in _options.CurrentValue.SigningCredentials select credentials.Key).ToList(); - // Import the symmetric encryption keys from the server configuration. + // Import the encryption keys from the server configuration. foreach (var credentials in _options.CurrentValue.EncryptionCredentials) { - if (credentials.Key is SymmetricSecurityKey) - { - options.EncryptionCredentials.Add(credentials); - } + options.EncryptionCredentials.Add(credentials); } options.UseReferenceAccessTokens = _options.CurrentValue.UseReferenceAccessTokens;