diff --git a/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs b/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs index b3c9055007..da8f3d269c 100644 --- a/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs +++ b/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs @@ -5,7 +5,6 @@ using Bit.Core.Models.Api; namespace Bit.Core.Auth.Models.Api.Response; -// TODO: in order to support opaque decryption via export key, we must update this to have a new option for opaque public class UserDecryptionOptions : ResponseModel { public UserDecryptionOptions() : base("userDecryptionOptions") @@ -30,10 +29,16 @@ public class UserDecryptionOptions : ResponseModel public TrustedDeviceUserDecryptionOption? TrustedDeviceOption { get; set; } /// - /// Gets or set information about the current users KeyConnector setup. + /// Gets or sets information about the current users KeyConnector setup. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public KeyConnectorUserDecryptionOption? KeyConnectorOption { get; set; } + + /// + /// Gets or sets information about the current OPAQUE setup. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public OpaqueUserDecryptionOption? OpaqueOption { get; set; } } public class WebAuthnPrfDecryptionOption @@ -84,3 +89,18 @@ public class KeyConnectorUserDecryptionOption KeyConnectorUrl = keyConnectorUrl; } } + + +public class OpaqueUserDecryptionOption +{ + public string EncryptedPrivateKey { get; } + public string EncryptedUserKey { get; } + + public OpaqueUserDecryptionOption( + string encryptedPrivateKey, + string encryptedUserKey) + { + EncryptedPrivateKey = encryptedPrivateKey; + EncryptedUserKey = encryptedUserKey; + } +} diff --git a/src/Identity/IdentityServer/UserDecryptionOptionsBuilder.cs b/src/Identity/IdentityServer/UserDecryptionOptionsBuilder.cs index 2dc1f2926b..04dd073a39 100644 --- a/src/Identity/IdentityServer/UserDecryptionOptionsBuilder.cs +++ b/src/Identity/IdentityServer/UserDecryptionOptionsBuilder.cs @@ -1,11 +1,14 @@ -using Bit.Core.Auth.Entities; +using Bit.Core; +using Bit.Core.Auth.Entities; using Bit.Core.Auth.Enums; using Bit.Core.Auth.Models.Api.Response; +using Bit.Core.Auth.Repositories; using Bit.Core.Auth.Utilities; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Repositories; +using Bit.Core.Services; using Bit.Identity.Utilities; namespace Bit.Identity.IdentityServer; @@ -21,6 +24,8 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder private readonly ICurrentContext _currentContext; private readonly IDeviceRepository _deviceRepository; private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IFeatureService _featureService; + private readonly IOpaqueKeyExchangeCredentialRepository _opaqueKeyExchangeCredentialRepository; private UserDecryptionOptions _options = new UserDecryptionOptions(); private User? _user; @@ -30,12 +35,16 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder public UserDecryptionOptionsBuilder( ICurrentContext currentContext, IDeviceRepository deviceRepository, - IOrganizationUserRepository organizationUserRepository + IOrganizationUserRepository organizationUserRepository, + IFeatureService featureService, + IOpaqueKeyExchangeCredentialRepository opaqueKeyExchangeCredentialRepository ) { _currentContext = currentContext; _deviceRepository = deviceRepository; _organizationUserRepository = organizationUserRepository; + _featureService = featureService; + _opaqueKeyExchangeCredentialRepository = opaqueKeyExchangeCredentialRepository; } public IUserDecryptionOptionsBuilder ForUser(User user) @@ -70,6 +79,7 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder { BuildKeyConnectorOptions(); await BuildTrustedDeviceOptions(); + await BuildOpaqueOption(); return _options; } @@ -151,4 +161,31 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder encryptedPrivateKey, encryptedUserKey); } + + private async Task BuildOpaqueOption() + { + + if (!_featureService.IsEnabled(FeatureFlagKeys.OpaqueKeyExchange)) + { + return; + } + + if (_user == null) + { + return; + } + + var credential = await _opaqueKeyExchangeCredentialRepository.GetByUserIdAsync(_user.Id); + + if (credential == null) + { + return; + } + + _options.OpaqueOption = new OpaqueUserDecryptionOption( + credential.EncryptedPrivateKey, + credential.EncryptedUserKey + ); + + } }