mirror of
https://github.com/bitwarden/server.git
synced 2024-11-25 12:45:18 +01:00
[PM-4614] Updating Duo to SDK v4 for Universal Prompt (#3664)
* added v4 updates * Fixed packages. * Null checks and OrganizationDuo * enable backwards compatibility support * updated validation * Update DuoUniversalPromptService.cs add JIRA ticket for cleanup * Update BaseRequestValidator.cs * updates to names and comments * fixed tests * fixed validation errros and authURL * updated naming * Filename change * Update BaseRequestValidator.cs
This commit is contained in:
parent
7577da083c
commit
0deb13791a
121
src/Core/Auth/Identity/TemporaryDuoWebV4SDKService.cs
Normal file
121
src/Core/Auth/Identity/TemporaryDuoWebV4SDKService.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
using Bit.Core.Auth.Models;
|
||||||
|
using Bit.Core.Context;
|
||||||
|
using Bit.Core.Entities;
|
||||||
|
using Bit.Core.Settings;
|
||||||
|
using Duo = DuoUniversal;
|
||||||
|
|
||||||
|
namespace Bit.Core.Auth.Identity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
PM-5156 addresses tech debt
|
||||||
|
Interface to allow for DI, will end up being removed as part of the removal of the old Duo SDK v2 flows.
|
||||||
|
This service is to support SDK v4 flows for Duo. At some time in the future we will need
|
||||||
|
to combine this service with the DuoWebTokenProvider and OrganizationDuoWebTokenProvider to support SDK v4.
|
||||||
|
*/
|
||||||
|
public interface ITemporaryDuoWebV4SDKService
|
||||||
|
{
|
||||||
|
Task<string> GenerateAsync(TwoFactorProvider provider, User user);
|
||||||
|
Task<bool> ValidateAsync(string token, TwoFactorProvider provider, User user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TemporaryDuoWebV4SDKService : ITemporaryDuoWebV4SDKService
|
||||||
|
{
|
||||||
|
private readonly ICurrentContext _currentContext;
|
||||||
|
private readonly GlobalSettings _globalSettings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for the DuoUniversalPromptService. Used to supplement v2 implementation of Duo with v4 SDK
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="currentContext">used to fetch initiating Client</param>
|
||||||
|
/// <param name="globalSettings">used to fetch vault URL for Redirect URL</param>
|
||||||
|
public TemporaryDuoWebV4SDKService(
|
||||||
|
ICurrentContext currentContext,
|
||||||
|
GlobalSettings globalSettings)
|
||||||
|
{
|
||||||
|
_currentContext = currentContext;
|
||||||
|
_globalSettings = globalSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provider agnostic (either Duo or OrganizationDuo) method to generate a Duo Auth URL
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="provider">Either Duo or OrganizationDuo</param>
|
||||||
|
/// <param name="user">self</param>
|
||||||
|
/// <returns>AuthUrl for DUO SDK v4</returns>
|
||||||
|
public async Task<string> GenerateAsync(TwoFactorProvider provider, User user)
|
||||||
|
{
|
||||||
|
if (!HasProperMetaData(provider))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var duoClient = await BuildDuoClientAsync(provider);
|
||||||
|
if (duoClient == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = Duo.Client.GenerateState(); //? Not sure on this yet. But required for GenerateAuthUrl
|
||||||
|
var authUrl = duoClient.GenerateAuthUri(user.Email, state);
|
||||||
|
|
||||||
|
return authUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates Duo SDK v4 response
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token">response form Duo</param>
|
||||||
|
/// <param name="provider">TwoFactorProviderType Duo or OrganizationDuo</param>
|
||||||
|
/// <param name="user">self</param>
|
||||||
|
/// <returns>true or false depending on result of verification</returns>
|
||||||
|
public async Task<bool> ValidateAsync(string token, TwoFactorProvider provider, User user)
|
||||||
|
{
|
||||||
|
if (!HasProperMetaData(provider))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var duoClient = await BuildDuoClientAsync(provider);
|
||||||
|
if (duoClient == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the result of the exchange doesn't throw an exception and it's not null, then it's valid
|
||||||
|
var res = await duoClient.ExchangeAuthorizationCodeFor2faResult(token, user.Email);
|
||||||
|
return res.AuthResult.Result == "allow";
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasProperMetaData(TwoFactorProvider provider)
|
||||||
|
{
|
||||||
|
return provider?.MetaData != null && provider.MetaData.ContainsKey("IKey") &&
|
||||||
|
provider.MetaData.ContainsKey("SKey") && provider.MetaData.ContainsKey("Host");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a Duo.Client object for use with Duo SDK v4. This combines the health check and the client generation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="provider">TwoFactorProvider Duo or OrganizationDuo</param>
|
||||||
|
/// <returns>Duo.Client object or null</returns>
|
||||||
|
private async Task<Duo.Client> BuildDuoClientAsync(TwoFactorProvider provider)
|
||||||
|
{
|
||||||
|
// Fetch Client name from header value since duo auth can be initiated from multiple clients and we want
|
||||||
|
// to redirect back to the correct client
|
||||||
|
_currentContext.HttpContext.Request.Headers.TryGetValue("Bitwarden-Client-Name", out var bitwardenClientName);
|
||||||
|
var redirectUri = string.Format("{0}/duo-redirect-connector.html?client={1}",
|
||||||
|
_globalSettings.BaseServiceUri.Vault, bitwardenClientName.FirstOrDefault() ?? "web");
|
||||||
|
|
||||||
|
var client = new Duo.ClientBuilder(
|
||||||
|
(string)provider.MetaData["IKey"],
|
||||||
|
(string)provider.MetaData["SKey"],
|
||||||
|
(string)provider.MetaData["Host"],
|
||||||
|
redirectUri).Build();
|
||||||
|
|
||||||
|
if (!await client.DoHealthCheck())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
@ -105,6 +105,7 @@ public static class FeatureFlagKeys
|
|||||||
public const string AutofillOverlay = "autofill-overlay";
|
public const string AutofillOverlay = "autofill-overlay";
|
||||||
public const string ItemShare = "item-share";
|
public const string ItemShare = "item-share";
|
||||||
public const string KeyRotationImprovements = "key-rotation-improvements";
|
public const string KeyRotationImprovements = "key-rotation-improvements";
|
||||||
|
public const string DuoRedirect = "duo-redirect";
|
||||||
public const string FlexibleCollectionsMigration = "flexible-collections-migration";
|
public const string FlexibleCollectionsMigration = "flexible-collections-migration";
|
||||||
public const string FlexibleCollectionsSignup = "flexible-collections-signup";
|
public const string FlexibleCollectionsSignup = "flexible-collections-signup";
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
|
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
|
||||||
<PackageReference Include="Azure.Storage.Queues" Version="12.12.0" />
|
<PackageReference Include="Azure.Storage.Queues" Version="12.12.0" />
|
||||||
<PackageReference Include="BitPay.Light" Version="1.0.1907" />
|
<PackageReference Include="BitPay.Light" Version="1.0.1907" />
|
||||||
|
<PackageReference Include="DuoUniversal" Version="1.2.1" />
|
||||||
<PackageReference Include="DnsClient" Version="1.7.0" />
|
<PackageReference Include="DnsClient" Version="1.7.0" />
|
||||||
<PackageReference Include="Fido2.AspNet" Version="3.0.1" />
|
<PackageReference Include="Fido2.AspNet" Version="3.0.1" />
|
||||||
<PackageReference Include="Handlebars.Net" Version="2.1.4" />
|
<PackageReference Include="Handlebars.Net" Version="2.1.4" />
|
||||||
|
@ -38,6 +38,7 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
private readonly IDeviceService _deviceService;
|
private readonly IDeviceService _deviceService;
|
||||||
private readonly IEventService _eventService;
|
private readonly IEventService _eventService;
|
||||||
private readonly IOrganizationDuoWebTokenProvider _organizationDuoWebTokenProvider;
|
private readonly IOrganizationDuoWebTokenProvider _organizationDuoWebTokenProvider;
|
||||||
|
private readonly ITemporaryDuoWebV4SDKService _duoWebV4SDKService;
|
||||||
private readonly IOrganizationRepository _organizationRepository;
|
private readonly IOrganizationRepository _organizationRepository;
|
||||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||||
private readonly IApplicationCacheService _applicationCacheService;
|
private readonly IApplicationCacheService _applicationCacheService;
|
||||||
@ -63,6 +64,7 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
IUserService userService,
|
IUserService userService,
|
||||||
IEventService eventService,
|
IEventService eventService,
|
||||||
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
||||||
|
ITemporaryDuoWebV4SDKService duoWebV4SDKService,
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
IApplicationCacheService applicationCacheService,
|
IApplicationCacheService applicationCacheService,
|
||||||
@ -84,6 +86,7 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
_userService = userService;
|
_userService = userService;
|
||||||
_eventService = eventService;
|
_eventService = eventService;
|
||||||
_organizationDuoWebTokenProvider = organizationDuoWebTokenProvider;
|
_organizationDuoWebTokenProvider = organizationDuoWebTokenProvider;
|
||||||
|
_duoWebV4SDKService = duoWebV4SDKService;
|
||||||
_organizationRepository = organizationRepository;
|
_organizationRepository = organizationRepository;
|
||||||
_organizationUserRepository = organizationUserRepository;
|
_organizationUserRepository = organizationUserRepository;
|
||||||
_applicationCacheService = applicationCacheService;
|
_applicationCacheService = applicationCacheService;
|
||||||
@ -167,7 +170,7 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We only want to track TOTPs in the chache to enforce one time use.
|
// We only want to track TOTPs in the cache to enforce one time use.
|
||||||
if (twoFactorProviderType == TwoFactorProviderType.Authenticator || twoFactorProviderType == TwoFactorProviderType.Email)
|
if (twoFactorProviderType == TwoFactorProviderType.Authenticator || twoFactorProviderType == TwoFactorProviderType.Email)
|
||||||
{
|
{
|
||||||
await Core.Utilities.DistributedCacheExtensions.SetAsync(_distributedCache, cacheKey, twoFactorToken, _cacheEntryOptions);
|
await Core.Utilities.DistributedCacheExtensions.SetAsync(_distributedCache, cacheKey, twoFactorToken, _cacheEntryOptions);
|
||||||
@ -428,10 +431,23 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
case TwoFactorProviderType.WebAuthn:
|
case TwoFactorProviderType.WebAuthn:
|
||||||
case TwoFactorProviderType.Remember:
|
case TwoFactorProviderType.Remember:
|
||||||
if (type != TwoFactorProviderType.Remember &&
|
if (type != TwoFactorProviderType.Remember &&
|
||||||
!(await _userService.TwoFactorProviderIsEnabledAsync(type, user)))
|
!await _userService.TwoFactorProviderIsEnabledAsync(type, user))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// DUO SDK v4 Update: try to validate the token - PM-5156 addresses tech debt
|
||||||
|
if (FeatureService.IsEnabled(FeatureFlagKeys.DuoRedirect))
|
||||||
|
{
|
||||||
|
if (type == TwoFactorProviderType.Duo)
|
||||||
|
{
|
||||||
|
if (!token.Contains(':'))
|
||||||
|
{
|
||||||
|
// We have to send the provider to the DuoWebV4SDKService to create the DuoClient
|
||||||
|
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Duo);
|
||||||
|
return await _duoWebV4SDKService.ValidateAsync(token, provider, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await _userManager.VerifyTwoFactorTokenAsync(user,
|
return await _userManager.VerifyTwoFactorTokenAsync(user,
|
||||||
CoreHelpers.CustomProviderName(type), token);
|
CoreHelpers.CustomProviderName(type), token);
|
||||||
@ -441,6 +457,20 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DUO SDK v4 Update: try to validate the token - PM-5156 addresses tech debt
|
||||||
|
if (FeatureService.IsEnabled(FeatureFlagKeys.DuoRedirect))
|
||||||
|
{
|
||||||
|
if (type == TwoFactorProviderType.OrganizationDuo)
|
||||||
|
{
|
||||||
|
if (!token.Contains(':'))
|
||||||
|
{
|
||||||
|
// We have to send the provider to the DuoWebV4SDKService to create the DuoClient
|
||||||
|
var provider = organization.GetTwoFactorProvider(TwoFactorProviderType.OrganizationDuo);
|
||||||
|
return await _duoWebV4SDKService.ValidateAsync(token, provider, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await _organizationDuoWebTokenProvider.ValidateAsync(token, organization, user);
|
return await _organizationDuoWebTokenProvider.ValidateAsync(token, organization, user);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -465,11 +495,19 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
CoreHelpers.CustomProviderName(type));
|
CoreHelpers.CustomProviderName(type));
|
||||||
if (type == TwoFactorProviderType.Duo)
|
if (type == TwoFactorProviderType.Duo)
|
||||||
{
|
{
|
||||||
return new Dictionary<string, object>
|
var duoResponse = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["Host"] = provider.MetaData["Host"],
|
["Host"] = provider.MetaData["Host"],
|
||||||
["Signature"] = token
|
["Signature"] = token
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// DUO SDK v4 Update: Duo-Redirect
|
||||||
|
if (FeatureService.IsEnabled(FeatureFlagKeys.DuoRedirect))
|
||||||
|
{
|
||||||
|
// Generate AuthUrl from DUO SDK v4 token provider
|
||||||
|
duoResponse.Add("AuthUrl", await _duoWebV4SDKService.GenerateAsync(provider, user));
|
||||||
|
}
|
||||||
|
return duoResponse;
|
||||||
}
|
}
|
||||||
else if (type == TwoFactorProviderType.WebAuthn)
|
else if (type == TwoFactorProviderType.WebAuthn)
|
||||||
{
|
{
|
||||||
@ -493,13 +531,19 @@ public abstract class BaseRequestValidator<T> where T : class
|
|||||||
case TwoFactorProviderType.OrganizationDuo:
|
case TwoFactorProviderType.OrganizationDuo:
|
||||||
if (await _organizationDuoWebTokenProvider.CanGenerateTwoFactorTokenAsync(organization))
|
if (await _organizationDuoWebTokenProvider.CanGenerateTwoFactorTokenAsync(organization))
|
||||||
{
|
{
|
||||||
return new Dictionary<string, object>
|
var duoResponse = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["Host"] = provider.MetaData["Host"],
|
["Host"] = provider.MetaData["Host"],
|
||||||
["Signature"] = await _organizationDuoWebTokenProvider.GenerateAsync(organization, user)
|
["Signature"] = await _organizationDuoWebTokenProvider.GenerateAsync(organization, user)
|
||||||
};
|
};
|
||||||
|
// DUO SDK v4 Update: DUO-Redirect
|
||||||
|
if (FeatureService.IsEnabled(FeatureFlagKeys.DuoRedirect))
|
||||||
|
{
|
||||||
|
// Generate AuthUrl from DUO SDK v4 token provider
|
||||||
|
duoResponse.Add("AuthUrl", await _duoWebV4SDKService.GenerateAsync(provider, user));
|
||||||
|
}
|
||||||
|
return duoResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
@ -33,6 +33,7 @@ public class CustomTokenRequestValidator : BaseRequestValidator<CustomTokenReque
|
|||||||
IUserService userService,
|
IUserService userService,
|
||||||
IEventService eventService,
|
IEventService eventService,
|
||||||
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
||||||
|
ITemporaryDuoWebV4SDKService duoWebV4SDKService,
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
IApplicationCacheService applicationCacheService,
|
IApplicationCacheService applicationCacheService,
|
||||||
@ -48,7 +49,7 @@ public class CustomTokenRequestValidator : BaseRequestValidator<CustomTokenReque
|
|||||||
IDistributedCache distributedCache,
|
IDistributedCache distributedCache,
|
||||||
IUserDecryptionOptionsBuilder userDecryptionOptionsBuilder)
|
IUserDecryptionOptionsBuilder userDecryptionOptionsBuilder)
|
||||||
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
||||||
organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository,
|
organizationDuoWebTokenProvider, duoWebV4SDKService, organizationRepository, organizationUserRepository,
|
||||||
applicationCacheService, mailService, logger, currentContext, globalSettings,
|
applicationCacheService, mailService, logger, currentContext, globalSettings,
|
||||||
userRepository, policyService, tokenDataFactory, featureService, ssoConfigRepository,
|
userRepository, policyService, tokenDataFactory, featureService, ssoConfigRepository,
|
||||||
distributedCache, userDecryptionOptionsBuilder)
|
distributedCache, userDecryptionOptionsBuilder)
|
||||||
|
@ -34,6 +34,7 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
|
|||||||
IUserService userService,
|
IUserService userService,
|
||||||
IEventService eventService,
|
IEventService eventService,
|
||||||
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
||||||
|
ITemporaryDuoWebV4SDKService duoWebV4SDKService,
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
IApplicationCacheService applicationCacheService,
|
IApplicationCacheService applicationCacheService,
|
||||||
@ -51,7 +52,7 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
|
|||||||
IDistributedCache distributedCache,
|
IDistributedCache distributedCache,
|
||||||
IUserDecryptionOptionsBuilder userDecryptionOptionsBuilder)
|
IUserDecryptionOptionsBuilder userDecryptionOptionsBuilder)
|
||||||
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
||||||
organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository,
|
organizationDuoWebTokenProvider, duoWebV4SDKService, organizationRepository, organizationUserRepository,
|
||||||
applicationCacheService, mailService, logger, currentContext, globalSettings, userRepository, policyService,
|
applicationCacheService, mailService, logger, currentContext, globalSettings, userRepository, policyService,
|
||||||
tokenDataFactory, featureService, ssoConfigRepository, distributedCache, userDecryptionOptionsBuilder)
|
tokenDataFactory, featureService, ssoConfigRepository, distributedCache, userDecryptionOptionsBuilder)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,7 @@ public class WebAuthnGrantValidator : BaseRequestValidator<ExtensionGrantValidat
|
|||||||
IUserService userService,
|
IUserService userService,
|
||||||
IEventService eventService,
|
IEventService eventService,
|
||||||
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
|
||||||
|
ITemporaryDuoWebV4SDKService duoWebV4SDKService,
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
IApplicationCacheService applicationCacheService,
|
IApplicationCacheService applicationCacheService,
|
||||||
@ -54,7 +55,7 @@ public class WebAuthnGrantValidator : BaseRequestValidator<ExtensionGrantValidat
|
|||||||
IAssertWebAuthnLoginCredentialCommand assertWebAuthnLoginCredentialCommand
|
IAssertWebAuthnLoginCredentialCommand assertWebAuthnLoginCredentialCommand
|
||||||
)
|
)
|
||||||
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
||||||
organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository,
|
organizationDuoWebTokenProvider, duoWebV4SDKService, organizationRepository, organizationUserRepository,
|
||||||
applicationCacheService, mailService, logger, currentContext, globalSettings,
|
applicationCacheService, mailService, logger, currentContext, globalSettings,
|
||||||
userRepository, policyService, tokenDataFactory, featureService, ssoConfigRepository, distributedCache, userDecryptionOptionsBuilder)
|
userRepository, policyService, tokenDataFactory, featureService, ssoConfigRepository, distributedCache, userDecryptionOptionsBuilder)
|
||||||
{
|
{
|
||||||
|
@ -376,7 +376,8 @@ public static class ServiceCollectionExtensions
|
|||||||
public static IdentityBuilder AddCustomIdentityServices(
|
public static IdentityBuilder AddCustomIdentityServices(
|
||||||
this IServiceCollection services, GlobalSettings globalSettings)
|
this IServiceCollection services, GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IOrganizationDuoWebTokenProvider, OrganizationDuoWebTokenProvider>();
|
services.AddScoped<IOrganizationDuoWebTokenProvider, OrganizationDuoWebTokenProvider>();
|
||||||
|
services.AddScoped<ITemporaryDuoWebV4SDKService, TemporaryDuoWebV4SDKService>();
|
||||||
services.Configure<PasswordHasherOptions>(options => options.IterationCount = 100000);
|
services.Configure<PasswordHasherOptions>(options => options.IterationCount = 100000);
|
||||||
services.Configure<TwoFactorRememberTokenProviderOptions>(options =>
|
services.Configure<TwoFactorRememberTokenProviderOptions>(options =>
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user