mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 23:52:50 -05:00
Add support for Key Connector OTP and account migration (#1663)
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
This commit is contained in:
@ -1,10 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class DeleteAccountRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Models.Api;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class EmailRequestModel
|
||||
public class EmailRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StrictEmailAddress]
|
||||
@ -12,9 +12,6 @@ namespace Bit.Core.Models.Api
|
||||
public string NewEmail { get; set; }
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string NewMasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
public string Token { get; set; }
|
||||
|
@ -1,16 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Models.Api;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class EmailTokenRequestModel
|
||||
public class EmailTokenRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StrictEmailAddress]
|
||||
[StringLength(256)]
|
||||
public string NewEmail { get; set; }
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,9 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class PasswordRequestModel
|
||||
public class PasswordRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string NewMasterPasswordHash { get; set; }
|
||||
|
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class SecretVerificationRequestModel : IValidatableObject
|
||||
{
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
public string OTP { get; set; }
|
||||
public string Secret => !string.IsNullOrEmpty(MasterPasswordHash) ? MasterPasswordHash : OTP;
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Secret))
|
||||
{
|
||||
yield return new ValidationResult("MasterPasswordHash or OTP must be supplied.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class SecurityStampRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Models.Api.Request.Accounts
|
||||
{
|
||||
public class SetCryptoAgentKeyRequestModel
|
||||
public class SetKeyConnectorKeyRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string Key { get; set; }
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class ApiKeyRequestModel
|
||||
public class VerifyOTPRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
public string OTP { get; set; }
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class VerifyPasswordRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class CipherPurgeRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class OrganizationDeleteRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ using Bit.Core.Sso;
|
||||
using U2F.Core.Utils;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using Bit.Core.Models.Table;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
@ -40,47 +39,11 @@ namespace Bit.Core.Models.Api
|
||||
{
|
||||
public SsoConfigurationDataRequest() {}
|
||||
|
||||
public SsoConfigurationDataRequest(SsoConfigurationData configurationData)
|
||||
{
|
||||
ConfigType = configurationData.ConfigType;
|
||||
UseCryptoAgent = configurationData.UseCryptoAgent;
|
||||
CryptoAgentUrl = configurationData.CryptoAgentUrl;
|
||||
Authority = configurationData.Authority;
|
||||
ClientId = configurationData.ClientId;
|
||||
ClientSecret = configurationData.ClientSecret;
|
||||
MetadataAddress = configurationData.MetadataAddress;
|
||||
RedirectBehavior = configurationData.RedirectBehavior;
|
||||
GetClaimsFromUserInfoEndpoint = configurationData.GetClaimsFromUserInfoEndpoint;
|
||||
IdpEntityId = configurationData.IdpEntityId;
|
||||
IdpBindingType = configurationData.IdpBindingType;
|
||||
IdpSingleSignOnServiceUrl = configurationData.IdpSingleSignOnServiceUrl;
|
||||
IdpSingleLogoutServiceUrl = configurationData.IdpSingleLogoutServiceUrl;
|
||||
IdpArtifactResolutionServiceUrl = configurationData.IdpArtifactResolutionServiceUrl;
|
||||
IdpX509PublicCert = configurationData.IdpX509PublicCert;
|
||||
IdpOutboundSigningAlgorithm = configurationData.IdpOutboundSigningAlgorithm;
|
||||
IdpAllowUnsolicitedAuthnResponse = configurationData.IdpAllowUnsolicitedAuthnResponse;
|
||||
IdpDisableOutboundLogoutRequests = configurationData.IdpDisableOutboundLogoutRequests;
|
||||
IdpWantAuthnRequestsSigned = configurationData.IdpWantAuthnRequestsSigned;
|
||||
SpNameIdFormat = configurationData.SpNameIdFormat;
|
||||
SpOutboundSigningAlgorithm = configurationData.SpOutboundSigningAlgorithm ?? SamlSigningAlgorithms.Sha256;
|
||||
SpSigningBehavior = configurationData.SpSigningBehavior;
|
||||
SpWantAssertionsSigned = configurationData.SpWantAssertionsSigned;
|
||||
SpValidateCertificates = configurationData.SpValidateCertificates;
|
||||
SpMinIncomingSigningAlgorithm = configurationData.SpMinIncomingSigningAlgorithm ?? SamlSigningAlgorithms.Sha256;
|
||||
AdditionalScopes = configurationData.AdditionalScopes;
|
||||
AdditionalUserIdClaimTypes = configurationData.AdditionalUserIdClaimTypes;
|
||||
AdditionalEmailClaimTypes = configurationData.AdditionalEmailClaimTypes;
|
||||
AdditionalNameClaimTypes = configurationData.AdditionalNameClaimTypes;
|
||||
AcrValues = configurationData.AcrValues;
|
||||
ExpectedReturnAcrValue = configurationData.ExpectedReturnAcrValue;
|
||||
}
|
||||
|
||||
[Required]
|
||||
public SsoType ConfigType { get; set; }
|
||||
|
||||
// Crypto Agent
|
||||
public bool UseCryptoAgent { get; set; }
|
||||
public string CryptoAgentUrl { get; set; }
|
||||
public bool UseKeyConnector { get; set; }
|
||||
public string KeyConnectorUrl { get; set; }
|
||||
|
||||
// OIDC
|
||||
public string Authority { get; set; }
|
||||
@ -215,8 +178,8 @@ namespace Bit.Core.Models.Api
|
||||
return new SsoConfigurationData
|
||||
{
|
||||
ConfigType = ConfigType,
|
||||
UseCryptoAgent = UseCryptoAgent,
|
||||
CryptoAgentUrl = CryptoAgentUrl,
|
||||
UseKeyConnector = UseKeyConnector,
|
||||
KeyConnectorUrl = KeyConnectorUrl,
|
||||
Authority = Authority,
|
||||
ClientId = ClientId,
|
||||
ClientSecret = ClientSecret,
|
||||
|
@ -7,7 +7,7 @@ using System.Linq;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class UpdateTwoFactorAuthenticatorRequestModel : TwoFactorRequestModel
|
||||
public class UpdateTwoFactorAuthenticatorRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
@ -38,7 +38,7 @@ namespace Bit.Core.Models.Api
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateTwoFactorDuoRequestModel : TwoFactorRequestModel, IValidatableObject
|
||||
public class UpdateTwoFactorDuoRequestModel : SecretVerificationRequestModel, IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
@ -111,7 +111,7 @@ namespace Bit.Core.Models.Api
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateTwoFactorYubicoOtpRequestModel : TwoFactorRequestModel, IValidatableObject
|
||||
public class UpdateTwoFactorYubicoOtpRequestModel : SecretVerificationRequestModel, IValidatableObject
|
||||
{
|
||||
public string Key1 { get; set; }
|
||||
public string Key2 { get; set; }
|
||||
@ -195,7 +195,7 @@ namespace Bit.Core.Models.Api
|
||||
}
|
||||
}
|
||||
|
||||
public class TwoFactorEmailRequestModel : TwoFactorRequestModel
|
||||
public class TwoFactorEmailRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
@ -231,13 +231,18 @@ namespace Bit.Core.Models.Api
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public class TwoFactorWebAuthnDeleteRequestModel : TwoFactorRequestModel, IValidatableObject
|
||||
public class TwoFactorWebAuthnDeleteRequestModel : SecretVerificationRequestModel, IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public int? Id { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
foreach (var validationResult in Validate(validationContext))
|
||||
{
|
||||
yield return validationResult;
|
||||
}
|
||||
|
||||
if (!Id.HasValue || Id < 0 || Id > 5)
|
||||
{
|
||||
yield return new ValidationResult("Invalid Key Id", new string[] { nameof(Id) });
|
||||
@ -252,18 +257,12 @@ namespace Bit.Core.Models.Api
|
||||
public string Token { get; set; }
|
||||
}
|
||||
|
||||
public class TwoFactorProviderRequestModel : TwoFactorRequestModel
|
||||
public class TwoFactorProviderRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
public TwoFactorProviderType? Type { get; set; }
|
||||
}
|
||||
|
||||
public class TwoFactorRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
|
||||
public class TwoFactorRecoveryRequestModel : TwoFactorEmailRequestModel
|
||||
{
|
||||
[Required]
|
||||
|
@ -79,6 +79,8 @@ namespace Bit.Core.Models.Api
|
||||
Email = organizationUser.Email;
|
||||
TwoFactorEnabled = twoFactorEnabled;
|
||||
SsoBound = !string.IsNullOrWhiteSpace(organizationUser.SsoExternalId);
|
||||
// Prevent reset password when using key connector.
|
||||
ResetPasswordEnrolled = ResetPasswordEnrolled && !organizationUser.UsesKeyConnector;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
@ -38,6 +38,12 @@ namespace Bit.Core.Models.Api
|
||||
UserId = organization.UserId?.ToString();
|
||||
ProviderId = organization.ProviderId?.ToString();
|
||||
ProviderName = organization.ProviderName;
|
||||
if (organization.SsoConfig != null)
|
||||
{
|
||||
var ssoConfigData = SsoConfigurationData.Deserialize(organization.SsoConfig);
|
||||
UsesKeyConnector = ssoConfigData.UseKeyConnector && !string.IsNullOrEmpty(ssoConfigData.KeyConnectorUrl);
|
||||
KeyConnectorUrl = ssoConfigData.KeyConnectorUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
@ -68,5 +74,7 @@ namespace Bit.Core.Models.Api
|
||||
public bool HasPublicAndPrivateKeys { get; set; }
|
||||
public string ProviderId { get; set; }
|
||||
public string ProviderName { get; set; }
|
||||
public bool UsesKeyConnector { get; set; }
|
||||
public string KeyConnectorUrl { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ namespace Bit.Core.Models.Api
|
||||
PrivateKey = user.PrivateKey;
|
||||
SecurityStamp = user.SecurityStamp;
|
||||
ForcePasswordReset = user.ForcePasswordReset;
|
||||
UsesKeyConnector = user.UsesKeyConnector;
|
||||
Organizations = organizationsUserDetails?.Select(o => new ProfileOrganizationResponseModel(o));
|
||||
Providers = providerUserDetails?.Select(p => new ProfileProviderResponseModel(p));
|
||||
ProviderOrganizations =
|
||||
@ -49,6 +50,7 @@ namespace Bit.Core.Models.Api
|
||||
public string PrivateKey { get; set; }
|
||||
public string SecurityStamp { get; set; }
|
||||
public bool ForcePasswordReset { get; set; }
|
||||
public bool UsesKeyConnector { get; set; }
|
||||
public IEnumerable<ProfileOrganizationResponseModel> Organizations { get; set; }
|
||||
public IEnumerable<ProfileProviderResponseModel> Providers { get; set; }
|
||||
public IEnumerable<ProfileProviderOrganizationResponseModel> ProviderOrganizations { get; set; }
|
||||
|
@ -33,5 +33,6 @@ namespace Bit.Core.Models.Data
|
||||
public string PrivateKey { get; set; }
|
||||
public Guid? ProviderId { get; set; }
|
||||
public string ProviderName { get; set; }
|
||||
public string SsoConfig { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ namespace Bit.Core.Models.Data
|
||||
public string SsoExternalId { get; set; }
|
||||
public string Permissions { get; set; }
|
||||
public string ResetPasswordKey { get; set; }
|
||||
public bool UsesKeyConnector { get; set; }
|
||||
|
||||
public Dictionary<TwoFactorProviderType, TwoFactorProvider> GetTwoFactorProviders()
|
||||
{
|
||||
|
@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Sso;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
|
||||
namespace Bit.Core.Models.Data
|
||||
@ -13,11 +15,20 @@ namespace Bit.Core.Models.Data
|
||||
private const string _oidcSignedOutPath = "/oidc-signedout";
|
||||
private const string _saml2ModulePath = "/saml2";
|
||||
|
||||
public static SsoConfigurationData Deserialize(string data)
|
||||
{
|
||||
return CoreHelpers.LoadClassFromJsonData<SsoConfigurationData>(data);
|
||||
}
|
||||
|
||||
public string Serialize()
|
||||
{
|
||||
return CoreHelpers.ClassToJsonData(this);
|
||||
}
|
||||
|
||||
public SsoType ConfigType { get; set; }
|
||||
|
||||
// Crypto Agent
|
||||
public bool UseCryptoAgent { get; set; }
|
||||
public string CryptoAgentUrl { get; set; }
|
||||
public bool UseKeyConnector { get; set; }
|
||||
public string KeyConnectorUrl { get; set; }
|
||||
|
||||
// OIDC
|
||||
public string Authority { get; set; }
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Core.Models.Table
|
||||
@ -13,11 +12,6 @@ namespace Bit.Core.Models.Table
|
||||
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
||||
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
||||
|
||||
private JsonSerializerOptions _jsonSerializerOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
};
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
// int will be auto-populated
|
||||
@ -26,12 +20,12 @@ namespace Bit.Core.Models.Table
|
||||
|
||||
public SsoConfigurationData GetData()
|
||||
{
|
||||
return JsonSerializer.Deserialize<SsoConfigurationData>(Data, _jsonSerializerOptions);
|
||||
return SsoConfigurationData.Deserialize(Data);
|
||||
}
|
||||
|
||||
public void SetData(SsoConfigurationData data)
|
||||
{
|
||||
Data = JsonSerializer.Serialize(data, _jsonSerializerOptions);
|
||||
Data = data.Serialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace Bit.Core.Models.Table
|
||||
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
||||
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
||||
public bool ForcePasswordReset { get; set; }
|
||||
public bool UsesCryptoAgent { get; set; }
|
||||
public bool UsesKeyConnector { get; set; }
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
|
Reference in New Issue
Block a user