Files
server/src/Identity/IdentityServer/BaseRequestValidator.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

576 lines
22 KiB
C#
Raw Normal View History

using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Security.Claims;
2021-03-22 23:21:43 +01:00
using System.Text.Json;
using Bit.Core;
[PM-1188] Server owner auth migration (#2825) * [PM-1188] add sso project to auth * [PM-1188] move sso api models to auth * [PM-1188] fix sso api model namespace & imports * [PM-1188] move core files to auth * [PM-1188] fix core sso namespace & models * [PM-1188] move sso repository files to auth * [PM-1188] fix sso repo files namespace & imports * [PM-1188] move sso sql files to auth folder * [PM-1188] move sso test files to auth folders * [PM-1188] fix sso tests namespace & imports * [PM-1188] move auth api files to auth folder * [PM-1188] fix auth api files namespace & imports * [PM-1188] move auth core files to auth folder * [PM-1188] fix auth core files namespace & imports * [PM-1188] move auth email templates to auth folder * [PM-1188] move auth email folder back into shared directory * [PM-1188] fix auth email names * [PM-1188] move auth core models to auth folder * [PM-1188] fix auth model namespace & imports * [PM-1188] add entire Identity project to auth codeowners * [PM-1188] fix auth orm files namespace & imports * [PM-1188] move auth orm files to auth folder * [PM-1188] move auth sql files to auth folder * [PM-1188] move auth tests to auth folder * [PM-1188] fix auth test files namespace & imports * [PM-1188] move emergency access api files to auth folder * [PM-1188] fix emergencyaccess api files namespace & imports * [PM-1188] move emergency access core files to auth folder * [PM-1188] fix emergency access core files namespace & imports * [PM-1188] move emergency access orm files to auth folder * [PM-1188] fix emergency access orm files namespace & imports * [PM-1188] move emergency access sql files to auth folder * [PM-1188] move emergencyaccess test files to auth folder * [PM-1188] fix emergency access test files namespace & imports * [PM-1188] move captcha files to auth folder * [PM-1188] fix captcha files namespace & imports * [PM-1188] move auth admin files into auth folder * [PM-1188] fix admin auth files namespace & imports - configure mvc to look in auth folders for views * [PM-1188] remove extra imports and formatting * [PM-1188] fix ef auth model imports * [PM-1188] fix DatabaseContextModelSnapshot paths * [PM-1188] fix grant import in ef * [PM-1188] update sqlproj * [PM-1188] move missed sqlproj files * [PM-1188] move auth ef models out of auth folder * [PM-1188] fix auth ef models namespace * [PM-1188] remove auth ef models unused imports * [PM-1188] fix imports for auth ef models * [PM-1188] fix more ef model imports * [PM-1188] fix file encodings
2023-04-14 13:25:56 -04:00
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Identity;
using Bit.Core.Auth.Models;
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Identity;
using Bit.Core.Models.Api;
[AC-1070] Enforce master password policy on login (#2714) * [EC-1070] Add API endpoint to retrieve all policies for the current user The additional API endpoint is required to avoid forcing a full sync call before every login for master password policy enforcement on login. * [EC-1070] Add MasterPasswordPolicyData model * [EC-1070] Move PolicyResponseModel to Core project The response model is used by both the Identity and Api projects. * [EC-1070] Supply master password polices as a custom identity token response * [EC-1070] Include master password policies in 2FA token response * [EC-1070] Add response model to verify-password endpoint that includes master password policies * [AC-1070] Introduce MasterPasswordPolicyResponseModel * [AC-1070] Add policy service method to retrieve a user's master password policy * [AC-1070] User new policy service method - Update BaseRequestValidator - Update AccountsController for /verify-password endpoint - Update VerifyMasterPasswordResponseModel to accept MasterPasswordPolicyData * [AC-1070] Cleanup new policy service method - Use User object instead of Guid - Remove TODO message - Use `PolicyRepository.GetManyByTypeApplicableToUserIdAsync` instead of filtering locally * [AC-1070] Cleanup MasterPasswordPolicy models - Remove default values from both models - Add missing `RequireLower` - Fix mismatched properties in `CombineWith` method - Make properties nullable in response model * [AC-1070] Remove now un-used GET /policies endpoint * [AC-1070] Update policy service method to use GetManyByUserIdAsync * [AC-1070] Ensure existing value is not null before comparison * [AC-1070] Remove redundant VerifyMasterPasswordResponse model * [AC-1070] Fix service typo in constructor
2023-04-17 07:35:47 -07:00
using Bit.Core.Models.Api.Response;
Feature/self hosted families for enterprise (#1991) * Families for enterprise/split up organization sponsorship service (#1829) * Split OrganizationSponsorshipService into commands * Use tokenable for token validation * Use interfaces to set up for DI * Use commands over services * Move service tests to command tests * Value types can't be null * Run dotnet format * Update src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/CancelSponsorshipCommand.cs Co-authored-by: Justin Baur <admin@justinbaur.com> * Fix controller tests Co-authored-by: Justin Baur <admin@justinbaur.com> * Families for enterprise/split up organization sponsorship service (#1875) * Split OrganizationSponsorshipService into commands * Use tokenable for token validation * Use interfaces to set up for DI * Use commands over services * Move service tests to command tests * Value types can't be null * Run dotnet format * Update src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/CancelSponsorshipCommand.cs Co-authored-by: Justin Baur <admin@justinbaur.com> * Fix controller tests * Split create and send sponsorships * Split up create sponsorship * Add self hosted commands to dependency injection * Add field to store cloud billing sync key on self host instances * Fix typo * Fix data protector purpose of sponsorship offers * Split cloud and selfhosted sponsorship offer tokenable * Generate offer from self hosted with all necessary auth data * Add Required properties to constructor * Split up cancel sponsorship command * Split revoke sponsorship command between cloud and self hosted * Fix/f4e multiple sponsorships (#1838) * Use sponosorship from validate to redeem * Update tests * Format * Remove sponsorship service * Run dotnet format * Fix self hosted only controller attribute * Clean up file structure and fixes * Remove unneeded tokenables * Remove obsolete commands * Do not require file/class prefix if unnecessary * Update Organizaiton sprocs * Remove unnecessary models * Fix tests * Generalize LicenseService path calculation Use async file read and deserialization * Use interfaces for testability * Remove unused usings * Correct test direction * Test license reading * remove unused usings * Format Co-authored-by: Justin Baur <admin@justinbaur.com> * Improve DataProtectorTokenFactory test coverage (#1884) * Add encstring to server * Test factory Co-authored-by: Carlos Muentes <cmuentes@bitwarden.com> * Format * Remove SymmetricKeyProtectedString Not needed * Set ForcInvalid Co-authored-by: Carlos Muentes <cmuentes@bitwarden.com> * Feature/self f4e/api keys (#1896) * Add in ApiKey * Work on API Key table * Work on apikey table * Fix response model * Work on information for UI * Work on last sync date * Work on sync status * Work on auth * Work on tokenable * Work on merge * Add custom requirement * Add policy * Run formatting * Work on EF Migrations * Work on OrganizationConnection * Work on database * Work on additional database table * Run formatting * Small fixes * More cleanup * Cleanup * Add RevisionDate * Add GO * Finish Sql project * Add newlines * Fix stored proc file * Fix sqlproj * Add newlines * Fix table * Add navigation property * Delete Connections when organization is deleted * Add connection validation * Start adding ID column * Work on ID column * Work on SQL migration * Work on migrations * Run formatting * Fix test build * Fix sprocs * Work on migrations * Fix Create table * Fix sproc * Add prints to migration * Add default value * Update EF migrations * Formatting * Add to integration tests * Minor fixes * Formatting * Cleanup * Address PR feedback * Address more PR feedback * Fix formatting * Fix formatting * Fix * Address PR feedback * Remove accidential change * Fix SQL build * Run formatting * Address PR feedback * Add sync data to OrganizationUserOrgDetails * Add comments * Remove OrganizationConnectionService interface * Remove unused using * Address PR feedback * Formatting * Minor fix * Feature/self f4e/update db (#1930) * Fix migration * Fix TimesRenewed * Add comments * Make two properties non-nullable * Remove need for SponsoredOrg on SH (#1934) * Remove need for SponsoredOrg on SH * Add Family prefix * Add check for enterprise org on BillingSync key (#1936) * [PS-10] Feature/sponsorships removed at end of term (#1938) * Rename commands to min unique names * Inject revoke command based on self hosting * WIP: Remove/Revoke marks to delete * Complete WIP * Improve remove/revoke tests * PR review * Fail validation if sponsorship has failed to sync for 6 months * Feature/do not accept old self host sponsorships (#1939) * Do not accept >6mo old self-hosted sponsorships * Give disabled grace period of 3 months * Fix issues of Sql.proj differing from migration outcome (#1942) * Fix issues of Sql.proj differing from migration outcome * Yoink int tests * Add missing assert helpers * Feature/org sponsorship sync (#1922) * Self-hosted side sync first pass TODO: * flush out org sponsorship model * implement cloud side * process cloud-side response and update self-hosted records * sync scaffolding second pass * remove list of Org User ids from sync and begin work on SelfHostedRevokeSponsorship * allow authenticated http calls from server to return a result * update models * add logic for sync and change offer email template * add billing sync key and hide CreateSponsorship without user * fix tests * add job scheduling * add authorize attributes to endpoints * separate models into data/model and request/response * batch sync more, add EnableCloudCommunication for testing * send emails in bulk * make userId and sponsorshipType non nullable * batch more on self hosted side of sync * remove TODOs and formatting * changed logic of cloud sync * let BaseIdentityClientService handle all logging * call sync from scheduled job on self host * create bulk db operations for OrganizationSponsorships * remove SponsoredOrgId from sync, return default from server http call * validate BillingSyncKey during sync revert changes to CreateSponsorshipCommand * revert changes to ICreateSponsorshipCommand * add some tests * add DeleteExpiredSponsorshipsJob * add cloud sync test * remove extra method * formatting * prevent new sponsorships from disabled orgs * update packages * - pulled out send sponsorship command dependency from sync on cloud - don't throw error when sponsorships are empty - formatting * formatting models * more formatting * remove licensingService dependency from selfhosted sync * use installation urls and formatting * create constructor for RequestModel and formatting * add date parameter to OrganizationSponsorship_DeleteExpired * add new migration * formatting * rename OrganizationCreateSponsorshipRequestModel to OrganizationSponsorshipCreateRequestModel * prevent whole sync from failing if one sponsorship type is unsupported * deserialize config and billingsynckey from org connection * alter log message when sync disabled * Add grace period to disabled orgs * return early on self hosted if there are no sponsorships in database * rename BillingSyncConfig * send sponsorship offers from controller * allow config to be a null object * better exception handling in sync scheduler * add ef migrations * formatting * fix tests * fix validate test Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * Fix OrganizationApiKey issues (#1941) Co-authored-by: Justin Baur <admin@justinbaur.com> * Feature/org sponsorship self hosted tests (#1947) * Self-hosted side sync first pass TODO: * flush out org sponsorship model * implement cloud side * process cloud-side response and update self-hosted records * sync scaffolding second pass * remove list of Org User ids from sync and begin work on SelfHostedRevokeSponsorship * allow authenticated http calls from server to return a result * update models * add logic for sync and change offer email template * add billing sync key and hide CreateSponsorship without user * fix tests * add job scheduling * add authorize attributes to endpoints * separate models into data/model and request/response * batch sync more, add EnableCloudCommunication for testing * send emails in bulk * make userId and sponsorshipType non nullable * batch more on self hosted side of sync * remove TODOs and formatting * changed logic of cloud sync * let BaseIdentityClientService handle all logging * call sync from scheduled job on self host * create bulk db operations for OrganizationSponsorships * remove SponsoredOrgId from sync, return default from server http call * validate BillingSyncKey during sync revert changes to CreateSponsorshipCommand * revert changes to ICreateSponsorshipCommand * add some tests * add DeleteExpiredSponsorshipsJob * add cloud sync test * remove extra method * formatting * prevent new sponsorships from disabled orgs * update packages * - pulled out send sponsorship command dependency from sync on cloud - don't throw error when sponsorships are empty - formatting * formatting models * more formatting * remove licensingService dependency from selfhosted sync * use installation urls and formatting * create constructor for RequestModel and formatting * add date parameter to OrganizationSponsorship_DeleteExpired * add new migration * formatting * rename OrganizationCreateSponsorshipRequestModel to OrganizationSponsorshipCreateRequestModel * prevent whole sync from failing if one sponsorship type is unsupported * deserialize config and billingsynckey from org connection * add mockHttp nuget package and use httpclientfactory * fix current tests * WIP of creating tests * WIP of new self hosted tests * WIP self hosted tests * finish self hosted tests * formatting * format of interface * remove extra config file * added newlines Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * Fix Organization_DeleteById (#1950) * Fix Organization_Delete * Fix L * [PS-4] block enterprise user from sponsoring itself (#1943) * [PS-248] Feature/add connections enabled endpoint (#1953) * Move Organization models to sub namespaces * Add Organization Connection api endpoints * Get all connections rather than just enabled ones * Add missing services to DI * pluralize private api endpoints * Add type protection to org connection request/response * Fix route * Use nullable Id to signify no connection * Test Get Connections enabled * Fix data discoverer * Also drop this sproc for rerunning * Id is the OUTPUT of create sprocs * Fix connection config parsing * Linter fixes * update sqlproj file name * Use param xdocs on methods * Simplify controller path attribute * Use JsonDocument to avoid escaped json in our response/request strings * Fix JsonDoc tests * Linter fixes * Fix ApiKey Command and add tests (#1949) * Fix ApiKey command * Formatting * Fix test failures introduced in #1943 (#1957) * Remove "Did you know?" copy from emails. (#1962) * Remove "Did you know" * Remove jsonIf helper * Feature/fix send single sponsorship offer email (#1956) * Fix sponsorship offer email * Do not sanitize org name * PR feedback * Feature/f4e sync event [PS-75] (#1963) * Create sponsorship sync event type * Add InstallationId to Event model * Add combinatorics-based test case generators * Log sponsorships sync event on sync * Linter and test fixes * Fix failing test * Migrate sprocs and view * Remove unused `using`s * [PS-190] Add manual sync trigger in self hosted (#1955) * WIP add button to admin project for billing sync * add connection table to view page * minor fixes for self hosted side of sync * fixes number of bugs for cloud side of sync * deserialize before returning for some reason * add json attributes to return models * list of sponsorships parameter is immutable, add secondary list * change sproc name * add error handling * Fix tests * modify call to connection * Update src/Admin/Controllers/OrganizationsController.cs Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * undo change to sproc name * simplify logic * Update src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/CloudSyncSponsorshipsCommand.cs Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * register services despite if self hosted or cloud * remove json properties * revert merge conflict Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * Update OrganizationSponsorship valid until when updating org expirati… (#1966) * Update OrganizationSponsorship valid until when updating org expiration date * Linter fixes * [PS-7] change revert email copy and add ValidUntil to sponsorship (#1965) * change revert email copy and add ValidUntil to sponsorship * add 15 days if no ValidUntil * Chore/merge/self hosted families for enterprise (#1972) * Log swallowed HttpRequestExceptions (#1866) Co-authored-by: Hinton <oscar@oscarhinton.com> * Allow for utilization of readonly db connection (#1937) * Bump the pin of the download-artifacts action to bypass the broken GitHub api (#1952) * Bumped version to 1.48.0 (#1958) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * [EC-160] Give Provider Users access to all org ciphers and collections (#1959) * Bumped version to 1.48.1 (#1961) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Avoid sending "user need confirmation" emails when there are no org admins (#1960) * Remove noncompliant users for new policies (#1951) * [PS-284] Allow installation clients to not need a user. (#1968) * Allow installation clients to not need a user. * Run formatting Co-authored-by: Andrei <30410186+Manolachi@users.noreply.github.com> Co-authored-by: Hinton <oscar@oscarhinton.com> Co-authored-by: sneakernuts <671942+sneakernuts@users.noreply.github.com> Co-authored-by: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Co-authored-by: Justin Baur <136baur@gmail.com> * Fix/license file not found (#1974) * Handle null license * Throw hint message if license is not found by the admin project. * Use CloudOrganizationId from Connection config * Change test to support change * Fix test Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * Feature/f4e selfhosted rename migration to .sql (#1971) * rename migration to .sql * format * Add unit tests to self host F4E (#1975) * Work on tests * Added more tests * Run linting * Address PR feedback * Fix AssertRecent * Linting * Fixed empty tests * Fix/misc self hosted f4e (#1973) * Allow setting of ApiUri * Return updates sponsorshipsData objects * Bind arguments by name * Greedy load sponsorships to email. When upsert was called, it creates Ids on _all_ records, which meant that the lazy-evaluation from this call always returned an empty list. * add scope for sync command DI in job. simplify error logic * update the sync job to get CloudOrgId from the BillingSyncKey Co-authored-by: Jacob Fink <jfink@bitwarden.com> * Chore/merge/self hosted families for enterprise (#1987) * Log swallowed HttpRequestExceptions (#1866) Co-authored-by: Hinton <oscar@oscarhinton.com> * Allow for utilization of readonly db connection (#1937) * Bump the pin of the download-artifacts action to bypass the broken GitHub api (#1952) * Bumped version to 1.48.0 (#1958) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * [EC-160] Give Provider Users access to all org ciphers and collections (#1959) * Bumped version to 1.48.1 (#1961) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Avoid sending "user need confirmation" emails when there are no org admins (#1960) * Remove noncompliant users for new policies (#1951) * [PS-284] Allow installation clients to not need a user. (#1968) * Allow installation clients to not need a user. * Run formatting * Use accept flow for sponsorship offers (#1964) * PS-82 check send 2FA email for new devices on TwoFactorController send-email-login (#1977) * [Bug] Skip WebAuthn 2fa event logs during login flow (#1978) * [Bug] Supress WebAuthn 2fa event logs during login process * Formatting * Simplified method call with new paramter input * Update RealIps Description (#1980) Describe the syntax of the real_ips configuration key with an example, to prevent type errors in the `setup` container when parsing `config.yml` * add proper URI validation to duo host (#1984) * captcha scores (#1967) * captcha scores * some api fixes * check bot on captcha attribute * Update src/Core/Services/Implementations/HCaptchaValidationService.cs Co-authored-by: e271828- <e271828-@users.noreply.github.com> Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> Co-authored-by: e271828- <e271828-@users.noreply.github.com> * ensure no path specific in duo host (#1985) Co-authored-by: Andrei <30410186+Manolachi@users.noreply.github.com> Co-authored-by: Hinton <oscar@oscarhinton.com> Co-authored-by: sneakernuts <671942+sneakernuts@users.noreply.github.com> Co-authored-by: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Co-authored-by: Justin Baur <136baur@gmail.com> Co-authored-by: Federico Maccaroni <fedemkr@gmail.com> Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Co-authored-by: Jordan Cooks <notnamed@users.noreply.github.com> Co-authored-by: Kyle Spearrin <kspearrin@users.noreply.github.com> Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> Co-authored-by: e271828- <e271828-@users.noreply.github.com> * Address feedback (#1990) Co-authored-by: Justin Baur <admin@justinbaur.com> Co-authored-by: Carlos Muentes <cmuentes@bitwarden.com> Co-authored-by: Jake Fink <jfink@bitwarden.com> Co-authored-by: Justin Baur <136baur@gmail.com> Co-authored-by: Andrei <30410186+Manolachi@users.noreply.github.com> Co-authored-by: Hinton <oscar@oscarhinton.com> Co-authored-by: sneakernuts <671942+sneakernuts@users.noreply.github.com> Co-authored-by: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Co-authored-by: Federico Maccaroni <fedemkr@gmail.com> Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Co-authored-by: Jordan Cooks <notnamed@users.noreply.github.com> Co-authored-by: Kyle Spearrin <kspearrin@users.noreply.github.com> Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> Co-authored-by: e271828- <e271828-@users.noreply.github.com>
2022-05-10 17:12:09 -04:00
using Bit.Core.Models.Data.Organizations;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Settings;
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
using Bit.Core.Tokens;
using Bit.Core.Utilities;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
namespace Bit.Identity.IdentityServer;
2022-08-29 16:06:55 -04:00
public abstract class BaseRequestValidator<T> where T : class
{
private UserManager<User> _userManager;
private readonly IDeviceRepository _deviceRepository;
private readonly IDeviceService _deviceService;
private readonly IUserService _userService;
private readonly IEventService _eventService;
private readonly IOrganizationDuoWebTokenProvider _organizationDuoWebTokenProvider;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IApplicationCacheService _applicationCacheService;
private readonly IMailService _mailService;
private readonly ILogger _logger;
private readonly ICurrentContext _currentContext;
private readonly GlobalSettings _globalSettings;
[AC-1070] Enforce master password policy on login (#2714) * [EC-1070] Add API endpoint to retrieve all policies for the current user The additional API endpoint is required to avoid forcing a full sync call before every login for master password policy enforcement on login. * [EC-1070] Add MasterPasswordPolicyData model * [EC-1070] Move PolicyResponseModel to Core project The response model is used by both the Identity and Api projects. * [EC-1070] Supply master password polices as a custom identity token response * [EC-1070] Include master password policies in 2FA token response * [EC-1070] Add response model to verify-password endpoint that includes master password policies * [AC-1070] Introduce MasterPasswordPolicyResponseModel * [AC-1070] Add policy service method to retrieve a user's master password policy * [AC-1070] User new policy service method - Update BaseRequestValidator - Update AccountsController for /verify-password endpoint - Update VerifyMasterPasswordResponseModel to accept MasterPasswordPolicyData * [AC-1070] Cleanup new policy service method - Use User object instead of Guid - Remove TODO message - Use `PolicyRepository.GetManyByTypeApplicableToUserIdAsync` instead of filtering locally * [AC-1070] Cleanup MasterPasswordPolicy models - Remove default values from both models - Add missing `RequireLower` - Fix mismatched properties in `CombineWith` method - Make properties nullable in response model * [AC-1070] Remove now un-used GET /policies endpoint * [AC-1070] Update policy service method to use GetManyByUserIdAsync * [AC-1070] Ensure existing value is not null before comparison * [AC-1070] Remove redundant VerifyMasterPasswordResponse model * [AC-1070] Fix service typo in constructor
2023-04-17 07:35:47 -07:00
private readonly IPolicyService _policyService;
[EC-787] Create a method in PolicyService to check if a policy applies to a user (#2537) * [EC-787] Add new stored procedure OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Add new method IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Add OrganizationUserPolicyDetails to represent policies applicable to a specific user * [EC-787] Add method IPolicyService.GetPoliciesApplicableToUser to filter the obtained policy data * [EC-787] Returning PolicyData on stored procedures * [EC-787] Changed GetPoliciesApplicableToUserAsync to return ICollection * [EC-787] Switched all usings of IPolicyRepository.GetManyByTypeApplicableToUserIdAsync to IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Removed policy logic from BaseRequestValidator and added usage of IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for OrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Changed integration test to check for single result * [EC-787] Marked IPolicyRepository methods GetManyByTypeApplicableToUserIdAsync and GetCountByTypeApplicableToUserIdAsync as obsolete * [EC-787] Returning OrganizationUserId on OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Remove deprecated stored procedures Policy_CountByTypeApplicableToUser, Policy_ReadByTypeApplicableToUser and function PolicyApplicableToUser * [EC-787] Added method IPolicyService.AnyPoliciesApplicableToUserAsync * [EC-787] Removed 'OrganizationUserType' parameter from queries * [EC-787] Formatted OrganizationUserPolicyDetailsCompare * [EC-787] Renamed SQL migration files * [EC-787] Changed OrganizationUser_ReadByUserIdWithPolicyDetails to return Permissions json * [EC-787] Refactored excluded user types for each Policy * [EC-787] Updated dates on dbo_future files * [EC-787] Remove dbo_future files from sql proj * [EC-787] Added parameter PolicyType to IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Rewrote OrganizationUser_ReadByUserIdWithPolicyDetails and added parameter for PolicyType * Update util/Migrator/DbScripts/2023-03-10_00_OrganizationUserReadByUserIdWithPolicyDetails.sql Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2023-05-12 08:22:19 +01:00
private readonly IUserRepository _userRepository;
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
private readonly IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> _tokenDataFactory;
public BaseRequestValidator(
UserManager<User> userManager,
IDeviceRepository deviceRepository,
IDeviceService deviceService,
IUserService userService,
IEventService eventService,
IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IApplicationCacheService applicationCacheService,
IMailService mailService,
ILogger logger,
ICurrentContext currentContext,
GlobalSettings globalSettings,
IPolicyRepository policyRepository,
[AC-1070] Enforce master password policy on login (#2714) * [EC-1070] Add API endpoint to retrieve all policies for the current user The additional API endpoint is required to avoid forcing a full sync call before every login for master password policy enforcement on login. * [EC-1070] Add MasterPasswordPolicyData model * [EC-1070] Move PolicyResponseModel to Core project The response model is used by both the Identity and Api projects. * [EC-1070] Supply master password polices as a custom identity token response * [EC-1070] Include master password policies in 2FA token response * [EC-1070] Add response model to verify-password endpoint that includes master password policies * [AC-1070] Introduce MasterPasswordPolicyResponseModel * [AC-1070] Add policy service method to retrieve a user's master password policy * [AC-1070] User new policy service method - Update BaseRequestValidator - Update AccountsController for /verify-password endpoint - Update VerifyMasterPasswordResponseModel to accept MasterPasswordPolicyData * [AC-1070] Cleanup new policy service method - Use User object instead of Guid - Remove TODO message - Use `PolicyRepository.GetManyByTypeApplicableToUserIdAsync` instead of filtering locally * [AC-1070] Cleanup MasterPasswordPolicy models - Remove default values from both models - Add missing `RequireLower` - Fix mismatched properties in `CombineWith` method - Make properties nullable in response model * [AC-1070] Remove now un-used GET /policies endpoint * [AC-1070] Update policy service method to use GetManyByUserIdAsync * [AC-1070] Ensure existing value is not null before comparison * [AC-1070] Remove redundant VerifyMasterPasswordResponse model * [AC-1070] Fix service typo in constructor
2023-04-17 07:35:47 -07:00
IUserRepository userRepository,
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
IPolicyService policyService,
IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> tokenDataFactory)
2022-08-29 14:53:16 -04:00
{
_userManager = userManager;
_deviceRepository = deviceRepository;
_deviceService = deviceService;
_userService = userService;
_eventService = eventService;
_organizationDuoWebTokenProvider = organizationDuoWebTokenProvider;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_applicationCacheService = applicationCacheService;
_mailService = mailService;
_logger = logger;
_currentContext = currentContext;
_globalSettings = globalSettings;
[EC-787] Create a method in PolicyService to check if a policy applies to a user (#2537) * [EC-787] Add new stored procedure OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Add new method IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Add OrganizationUserPolicyDetails to represent policies applicable to a specific user * [EC-787] Add method IPolicyService.GetPoliciesApplicableToUser to filter the obtained policy data * [EC-787] Returning PolicyData on stored procedures * [EC-787] Changed GetPoliciesApplicableToUserAsync to return ICollection * [EC-787] Switched all usings of IPolicyRepository.GetManyByTypeApplicableToUserIdAsync to IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Removed policy logic from BaseRequestValidator and added usage of IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for OrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Changed integration test to check for single result * [EC-787] Marked IPolicyRepository methods GetManyByTypeApplicableToUserIdAsync and GetCountByTypeApplicableToUserIdAsync as obsolete * [EC-787] Returning OrganizationUserId on OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Remove deprecated stored procedures Policy_CountByTypeApplicableToUser, Policy_ReadByTypeApplicableToUser and function PolicyApplicableToUser * [EC-787] Added method IPolicyService.AnyPoliciesApplicableToUserAsync * [EC-787] Removed 'OrganizationUserType' parameter from queries * [EC-787] Formatted OrganizationUserPolicyDetailsCompare * [EC-787] Renamed SQL migration files * [EC-787] Changed OrganizationUser_ReadByUserIdWithPolicyDetails to return Permissions json * [EC-787] Refactored excluded user types for each Policy * [EC-787] Updated dates on dbo_future files * [EC-787] Remove dbo_future files from sql proj * [EC-787] Added parameter PolicyType to IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Rewrote OrganizationUser_ReadByUserIdWithPolicyDetails and added parameter for PolicyType * Update util/Migrator/DbScripts/2023-03-10_00_OrganizationUserReadByUserIdWithPolicyDetails.sql Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2023-05-12 08:22:19 +01:00
_policyService = policyService;
_userRepository = userRepository;
[AC-1070] Enforce master password policy on login (#2714) * [EC-1070] Add API endpoint to retrieve all policies for the current user The additional API endpoint is required to avoid forcing a full sync call before every login for master password policy enforcement on login. * [EC-1070] Add MasterPasswordPolicyData model * [EC-1070] Move PolicyResponseModel to Core project The response model is used by both the Identity and Api projects. * [EC-1070] Supply master password polices as a custom identity token response * [EC-1070] Include master password policies in 2FA token response * [EC-1070] Add response model to verify-password endpoint that includes master password policies * [AC-1070] Introduce MasterPasswordPolicyResponseModel * [AC-1070] Add policy service method to retrieve a user's master password policy * [AC-1070] User new policy service method - Update BaseRequestValidator - Update AccountsController for /verify-password endpoint - Update VerifyMasterPasswordResponseModel to accept MasterPasswordPolicyData * [AC-1070] Cleanup new policy service method - Use User object instead of Guid - Remove TODO message - Use `PolicyRepository.GetManyByTypeApplicableToUserIdAsync` instead of filtering locally * [AC-1070] Cleanup MasterPasswordPolicy models - Remove default values from both models - Add missing `RequireLower` - Fix mismatched properties in `CombineWith` method - Make properties nullable in response model * [AC-1070] Remove now un-used GET /policies endpoint * [AC-1070] Update policy service method to use GetManyByUserIdAsync * [AC-1070] Ensure existing value is not null before comparison * [AC-1070] Remove redundant VerifyMasterPasswordResponse model * [AC-1070] Fix service typo in constructor
2023-04-17 07:35:47 -07:00
_policyService = policyService;
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
_tokenDataFactory = tokenDataFactory;
2022-08-29 14:53:16 -04:00
}
protected async Task ValidateAsync(T context, ValidatedTokenRequest request,
CustomValidatorRequestContext validatorContext)
2022-08-29 16:06:55 -04:00
{
var isBot = (validatorContext.CaptchaResponse?.IsBot ?? false);
if (isBot)
2022-08-29 16:06:55 -04:00
{
_logger.LogInformation(Constants.BypassFiltersEventId,
"Login attempt for {0} detected as a captcha bot with score {1}.",
request.UserName, validatorContext.CaptchaResponse.Score);
2022-08-29 16:06:55 -04:00
}
2022-08-29 14:53:16 -04:00
var twoFactorToken = request.Raw["TwoFactorToken"]?.ToString();
var twoFactorProvider = request.Raw["TwoFactorProvider"]?.ToString();
var twoFactorRemember = request.Raw["TwoFactorRemember"]?.ToString() == "1";
var twoFactorRequest = !string.IsNullOrWhiteSpace(twoFactorToken) &&
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
!string.IsNullOrWhiteSpace(twoFactorProvider);
2022-08-29 16:06:55 -04:00
var valid = await ValidateContextAsync(context, validatorContext);
var user = validatorContext.User;
if (!valid)
{
await UpdateFailedAuthDetailsAsync(user, false, !validatorContext.KnownDevice);
}
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
if (!valid || isBot)
2022-08-29 16:06:55 -04:00
{
await BuildErrorResultAsync("Username or password is incorrect. Try again.", false, context, user);
2022-08-29 16:06:55 -04:00
return;
}
var (isTwoFactorRequired, twoFactorOrganization) = await RequiresTwoFactorAsync(user, request);
if (isTwoFactorRequired)
2022-08-29 16:06:55 -04:00
{
// Just defaulting it
var twoFactorProviderType = TwoFactorProviderType.Authenticator;
if (!twoFactorRequest || !Enum.TryParse(twoFactorProvider, out twoFactorProviderType))
{
await BuildTwoFactorResultAsync(user, twoFactorOrganization, context);
return;
}
var verified = await VerifyTwoFactor(user, twoFactorOrganization,
twoFactorProviderType, twoFactorToken);
if ((!verified || isBot) && twoFactorProviderType != TwoFactorProviderType.Remember)
{
await UpdateFailedAuthDetailsAsync(user, true, !validatorContext.KnownDevice);
await BuildErrorResultAsync("Two-step token is invalid. Try again.", true, context, user);
return;
}
else if ((!verified || isBot) && twoFactorProviderType == TwoFactorProviderType.Remember)
{
// Delay for brute force.
await Task.Delay(2000);
await BuildTwoFactorResultAsync(user, twoFactorOrganization, context);
2022-08-29 16:06:55 -04:00
return;
}
2022-08-29 16:06:55 -04:00
}
else
2022-08-29 16:06:55 -04:00
{
twoFactorRequest = false;
twoFactorRemember = false;
twoFactorToken = null;
2022-08-29 16:06:55 -04:00
}
// Returns true if can finish validation process
if (await IsValidAuthTypeAsync(user, request.GrantType))
2022-08-29 16:06:55 -04:00
{
var device = await SaveDeviceAsync(user, request);
if (device == null)
{
await BuildErrorResultAsync("No device information provided.", false, context, user);
return;
}
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
await BuildSuccessResultAsync(user, context, device, twoFactorRequest && twoFactorRemember);
2022-08-29 14:53:16 -04:00
}
2022-08-29 16:06:55 -04:00
else
{
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
SetSsoResult(context,
new Dictionary<string, object>
{
{ "ErrorModel", new ErrorResponseModel("SSO authentication is required.") }
});
2022-08-29 16:06:55 -04:00
}
}
protected abstract Task<bool> ValidateContextAsync(T context, CustomValidatorRequestContext validatorContext);
protected async Task BuildSuccessResultAsync(User user, T context, Device device, bool sendRememberToken)
2022-08-29 16:06:55 -04:00
{
await _eventService.LogUserEventAsync(user.Id, EventType.User_LoggedIn);
2022-08-29 16:06:55 -04:00
var claims = new List<Claim>();
2022-08-29 16:06:55 -04:00
if (device != null)
{
claims.Add(new Claim(Claims.Device, device.Identifier));
2022-08-29 16:06:55 -04:00
}
var customResponse = new Dictionary<string, object>();
if (!string.IsNullOrWhiteSpace(user.PrivateKey))
2022-08-29 16:06:55 -04:00
{
customResponse.Add("PrivateKey", user.PrivateKey);
2022-08-29 16:06:55 -04:00
}
if (!string.IsNullOrWhiteSpace(user.Key))
{
customResponse.Add("Key", user.Key);
}
[AC-1070] Enforce master password policy on login (#2714) * [EC-1070] Add API endpoint to retrieve all policies for the current user The additional API endpoint is required to avoid forcing a full sync call before every login for master password policy enforcement on login. * [EC-1070] Add MasterPasswordPolicyData model * [EC-1070] Move PolicyResponseModel to Core project The response model is used by both the Identity and Api projects. * [EC-1070] Supply master password polices as a custom identity token response * [EC-1070] Include master password policies in 2FA token response * [EC-1070] Add response model to verify-password endpoint that includes master password policies * [AC-1070] Introduce MasterPasswordPolicyResponseModel * [AC-1070] Add policy service method to retrieve a user's master password policy * [AC-1070] User new policy service method - Update BaseRequestValidator - Update AccountsController for /verify-password endpoint - Update VerifyMasterPasswordResponseModel to accept MasterPasswordPolicyData * [AC-1070] Cleanup new policy service method - Use User object instead of Guid - Remove TODO message - Use `PolicyRepository.GetManyByTypeApplicableToUserIdAsync` instead of filtering locally * [AC-1070] Cleanup MasterPasswordPolicy models - Remove default values from both models - Add missing `RequireLower` - Fix mismatched properties in `CombineWith` method - Make properties nullable in response model * [AC-1070] Remove now un-used GET /policies endpoint * [AC-1070] Update policy service method to use GetManyByUserIdAsync * [AC-1070] Ensure existing value is not null before comparison * [AC-1070] Remove redundant VerifyMasterPasswordResponse model * [AC-1070] Fix service typo in constructor
2023-04-17 07:35:47 -07:00
customResponse.Add("MasterPasswordPolicy", await GetMasterPasswordPolicy(user));
customResponse.Add("ForcePasswordReset", user.ForcePasswordReset);
customResponse.Add("ResetMasterPassword", string.IsNullOrWhiteSpace(user.MasterPassword));
customResponse.Add("Kdf", (byte)user.Kdf);
customResponse.Add("KdfIterations", user.KdfIterations);
customResponse.Add("KdfMemory", user.KdfMemory);
customResponse.Add("KdfParallelism", user.KdfParallelism);
if (sendRememberToken)
2022-08-29 16:06:55 -04:00
{
var token = await _userManager.GenerateTwoFactorTokenAsync(user,
CoreHelpers.CustomProviderName(TwoFactorProviderType.Remember));
customResponse.Add("TwoFactorToken", token);
}
await ResetFailedAuthDetailsAsync(user);
await SetSuccessResult(context, user, claims, customResponse);
2022-08-29 16:06:55 -04:00
}
protected async Task BuildTwoFactorResultAsync(User user, Organization organization, T context)
2022-08-29 16:06:55 -04:00
{
var providerKeys = new List<byte>();
var providers = new Dictionary<string, Dictionary<string, object>>();
var enabledProviders = new List<KeyValuePair<TwoFactorProviderType, TwoFactorProvider>>();
if (organization?.GetTwoFactorProviders() != null)
2022-08-29 16:06:55 -04:00
{
enabledProviders.AddRange(organization.GetTwoFactorProviders().Where(
p => organization.TwoFactorProviderIsEnabled(p.Key)));
}
if (user.GetTwoFactorProviders() != null)
{
foreach (var p in user.GetTwoFactorProviders())
{
if (await _userService.TwoFactorProviderIsEnabledAsync(p.Key, user))
{
enabledProviders.Add(p);
}
}
2022-08-29 16:06:55 -04:00
}
if (!enabledProviders.Any())
2022-08-29 16:06:55 -04:00
{
await BuildErrorResultAsync("No two-step providers enabled.", false, context, user);
return;
}
foreach (var provider in enabledProviders)
2022-08-29 14:53:16 -04:00
{
providerKeys.Add((byte)provider.Key);
var infoDict = await BuildTwoFactorParams(organization, user, provider.Key, provider.Value);
providers.Add(((byte)provider.Key).ToString(), infoDict);
}
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
var twoFactorResultDict = new Dictionary<string, object>
{
{ "TwoFactorProviders", providers.Keys },
{ "TwoFactorProviders2", providers },
{ "MasterPasswordPolicy", await GetMasterPasswordPolicy(user) },
};
// If we have email as a 2FA provider, we might need an SsoEmail2fa Session Token
if (enabledProviders.Any(p => p.Key == TwoFactorProviderType.Email))
{
twoFactorResultDict.Add("SsoEmail2faSessionToken",
_tokenDataFactory.Protect(new SsoEmail2faSessionTokenable(user)));
twoFactorResultDict.Add("Email", user.Email);
}
SetTwoFactorResult(context, twoFactorResultDict);
2022-08-29 16:06:55 -04:00
if (enabledProviders.Count() == 1 && enabledProviders.First().Key == TwoFactorProviderType.Email)
2022-08-29 16:06:55 -04:00
{
// Send email now if this is their only 2FA method
await _userService.SendTwoFactorEmailAsync(user);
2022-08-29 14:53:16 -04:00
}
2022-08-29 16:06:55 -04:00
}
protected async Task BuildErrorResultAsync(string message, bool twoFactorRequest, T context, User user)
2022-08-29 16:06:55 -04:00
{
if (user != null)
2022-08-29 16:06:55 -04:00
{
await _eventService.LogUserEventAsync(user.Id,
2022-08-29 14:53:16 -04:00
twoFactorRequest ? EventType.User_FailedLogIn2fa : EventType.User_FailedLogIn);
}
if (_globalSettings.SelfHosted)
2022-08-29 16:06:55 -04:00
{
_logger.LogWarning(Constants.BypassFiltersEventId,
string.Format("Failed login attempt{0}{1}", twoFactorRequest ? ", 2FA invalid." : ".",
$" {_currentContext.IpAddress}"));
2022-08-29 16:06:55 -04:00
}
await Task.Delay(2000); // Delay for brute force.
SetErrorResult(context,
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
new Dictionary<string, object> { { "ErrorModel", new ErrorResponseModel(message) } });
2022-08-29 16:06:55 -04:00
}
protected abstract void SetTwoFactorResult(T context, Dictionary<string, object> customResponse);
2022-08-29 14:53:16 -04:00
protected abstract void SetSsoResult(T context, Dictionary<string, object> customResponse);
2022-08-29 14:53:16 -04:00
protected abstract Task SetSuccessResult(T context, User user, List<Claim> claims,
Dictionary<string, object> customResponse);
2022-08-29 16:06:55 -04:00
protected abstract void SetErrorResult(T context, Dictionary<string, object> customResponse);
2022-08-29 16:06:55 -04:00
private async Task<Tuple<bool, Organization>> RequiresTwoFactorAsync(User user, ValidatedTokenRequest request)
2022-08-29 16:06:55 -04:00
{
if (request.GrantType == "client_credentials")
{
// Do not require MFA for api key logins
return new Tuple<bool, Organization>(false, null);
}
var individualRequired = _userManager.SupportsUserTwoFactor &&
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
await _userManager.GetTwoFactorEnabledAsync(user) &&
(await _userManager.GetValidTwoFactorProvidersAsync(user)).Count > 0;
Organization firstEnabledOrg = null;
var orgs = (await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, user.Id))
.ToList();
if (orgs.Any())
2022-08-29 16:06:55 -04:00
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var twoFactorOrgs = orgs.Where(o => OrgUsing2fa(orgAbilities, o.Id));
if (twoFactorOrgs.Any())
{
var userOrgs = await _organizationRepository.GetManyByUserIdAsync(user.Id);
firstEnabledOrg = userOrgs.FirstOrDefault(
o => orgs.Any(om => om.Id == o.Id) && o.TwoFactorIsEnabled());
}
2022-08-29 16:06:55 -04:00
}
return new Tuple<bool, Organization>(individualRequired || firstEnabledOrg != null, firstEnabledOrg);
}
private async Task<bool> IsValidAuthTypeAsync(User user, string grantType)
2022-08-29 16:06:55 -04:00
{
if (grantType == "authorization_code" || grantType == "client_credentials")
{
// Already using SSO to authorize, finish successfully
// Or login via api key, skip SSO requirement
return true;
}
[EC-787] Create a method in PolicyService to check if a policy applies to a user (#2537) * [EC-787] Add new stored procedure OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Add new method IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Add OrganizationUserPolicyDetails to represent policies applicable to a specific user * [EC-787] Add method IPolicyService.GetPoliciesApplicableToUser to filter the obtained policy data * [EC-787] Returning PolicyData on stored procedures * [EC-787] Changed GetPoliciesApplicableToUserAsync to return ICollection * [EC-787] Switched all usings of IPolicyRepository.GetManyByTypeApplicableToUserIdAsync to IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Removed policy logic from BaseRequestValidator and added usage of IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for OrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Changed integration test to check for single result * [EC-787] Marked IPolicyRepository methods GetManyByTypeApplicableToUserIdAsync and GetCountByTypeApplicableToUserIdAsync as obsolete * [EC-787] Returning OrganizationUserId on OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Remove deprecated stored procedures Policy_CountByTypeApplicableToUser, Policy_ReadByTypeApplicableToUser and function PolicyApplicableToUser * [EC-787] Added method IPolicyService.AnyPoliciesApplicableToUserAsync * [EC-787] Removed 'OrganizationUserType' parameter from queries * [EC-787] Formatted OrganizationUserPolicyDetailsCompare * [EC-787] Renamed SQL migration files * [EC-787] Changed OrganizationUser_ReadByUserIdWithPolicyDetails to return Permissions json * [EC-787] Refactored excluded user types for each Policy * [EC-787] Updated dates on dbo_future files * [EC-787] Remove dbo_future files from sql proj * [EC-787] Added parameter PolicyType to IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Rewrote OrganizationUser_ReadByUserIdWithPolicyDetails and added parameter for PolicyType * Update util/Migrator/DbScripts/2023-03-10_00_OrganizationUserReadByUserIdWithPolicyDetails.sql Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2023-05-12 08:22:19 +01:00
// Check if user belongs to any organization with an active SSO policy
var anySsoPoliciesApplicableToUser = await _policyService.AnyPoliciesApplicableToUserAsync(user.Id, PolicyType.RequireSso, OrganizationUserStatusType.Confirmed);
if (anySsoPoliciesApplicableToUser)
{
[EC-787] Create a method in PolicyService to check if a policy applies to a user (#2537) * [EC-787] Add new stored procedure OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Add new method IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Add OrganizationUserPolicyDetails to represent policies applicable to a specific user * [EC-787] Add method IPolicyService.GetPoliciesApplicableToUser to filter the obtained policy data * [EC-787] Returning PolicyData on stored procedures * [EC-787] Changed GetPoliciesApplicableToUserAsync to return ICollection * [EC-787] Switched all usings of IPolicyRepository.GetManyByTypeApplicableToUserIdAsync to IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Removed policy logic from BaseRequestValidator and added usage of IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for OrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Changed integration test to check for single result * [EC-787] Marked IPolicyRepository methods GetManyByTypeApplicableToUserIdAsync and GetCountByTypeApplicableToUserIdAsync as obsolete * [EC-787] Returning OrganizationUserId on OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Remove deprecated stored procedures Policy_CountByTypeApplicableToUser, Policy_ReadByTypeApplicableToUser and function PolicyApplicableToUser * [EC-787] Added method IPolicyService.AnyPoliciesApplicableToUserAsync * [EC-787] Removed 'OrganizationUserType' parameter from queries * [EC-787] Formatted OrganizationUserPolicyDetailsCompare * [EC-787] Renamed SQL migration files * [EC-787] Changed OrganizationUser_ReadByUserIdWithPolicyDetails to return Permissions json * [EC-787] Refactored excluded user types for each Policy * [EC-787] Updated dates on dbo_future files * [EC-787] Remove dbo_future files from sql proj * [EC-787] Added parameter PolicyType to IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Rewrote OrganizationUser_ReadByUserIdWithPolicyDetails and added parameter for PolicyType * Update util/Migrator/DbScripts/2023-03-10_00_OrganizationUserReadByUserIdWithPolicyDetails.sql Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2023-05-12 08:22:19 +01:00
return false;
2022-08-29 14:53:16 -04:00
}
// Default - continue validation process
return true;
}
private bool OrgUsing2fa(IDictionary<Guid, OrganizationAbility> orgAbilities, Guid orgId)
2022-08-29 14:53:16 -04:00
{
return orgAbilities != null && orgAbilities.ContainsKey(orgId) &&
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
orgAbilities[orgId].Enabled && orgAbilities[orgId].Using2fa;
}
private Device GetDeviceFromRequest(ValidatedRequest request)
2022-08-29 16:06:55 -04:00
{
var deviceIdentifier = request.Raw["DeviceIdentifier"]?.ToString();
var deviceType = request.Raw["DeviceType"]?.ToString();
var deviceName = request.Raw["DeviceName"]?.ToString();
var devicePushToken = request.Raw["DevicePushToken"]?.ToString();
if (string.IsNullOrWhiteSpace(deviceIdentifier) || string.IsNullOrWhiteSpace(deviceType) ||
string.IsNullOrWhiteSpace(deviceName) || !Enum.TryParse(deviceType, out DeviceType type))
2022-08-29 16:06:55 -04:00
{
return null;
}
return new Device
2022-08-29 16:06:55 -04:00
{
Identifier = deviceIdentifier,
Name = deviceName,
Type = type,
PushToken = string.IsNullOrWhiteSpace(devicePushToken) ? null : devicePushToken
2022-08-29 16:06:55 -04:00
};
}
private async Task<bool> VerifyTwoFactor(User user, Organization organization, TwoFactorProviderType type,
string token)
2022-08-29 16:06:55 -04:00
{
switch (type)
{
case TwoFactorProviderType.Authenticator:
case TwoFactorProviderType.Email:
case TwoFactorProviderType.Duo:
case TwoFactorProviderType.YubiKey:
2021-03-22 23:21:43 +01:00
case TwoFactorProviderType.WebAuthn:
case TwoFactorProviderType.Remember:
if (type != TwoFactorProviderType.Remember &&
!(await _userService.TwoFactorProviderIsEnabledAsync(type, user)))
2022-08-29 14:53:16 -04:00
{
return false;
}
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
return await _userManager.VerifyTwoFactorTokenAsync(user,
CoreHelpers.CustomProviderName(type), token);
case TwoFactorProviderType.OrganizationDuo:
if (!organization?.TwoFactorProviderIsEnabled(type) ?? true)
2022-08-29 16:06:55 -04:00
{
return false;
2022-08-29 16:06:55 -04:00
}
return await _organizationDuoWebTokenProvider.ValidateAsync(token, organization, user);
2022-08-29 16:06:55 -04:00
default:
return false;
}
2022-08-29 16:06:55 -04:00
}
private async Task<Dictionary<string, object>> BuildTwoFactorParams(Organization organization, User user,
TwoFactorProviderType type, TwoFactorProvider provider)
2022-08-29 16:06:55 -04:00
{
switch (type)
{
case TwoFactorProviderType.Duo:
2021-03-22 23:21:43 +01:00
case TwoFactorProviderType.WebAuthn:
case TwoFactorProviderType.Email:
case TwoFactorProviderType.YubiKey:
2021-03-22 23:21:43 +01:00
if (!(await _userService.TwoFactorProviderIsEnabledAsync(type, user)))
{
return null;
2021-03-22 23:21:43 +01:00
}
2022-08-29 14:53:16 -04:00
2021-03-22 23:21:43 +01:00
var token = await _userManager.GenerateTwoFactorTokenAsync(user,
CoreHelpers.CustomProviderName(type));
if (type == TwoFactorProviderType.Duo)
2022-08-29 16:06:55 -04:00
{
return new Dictionary<string, object>
{
["Host"] = provider.MetaData["Host"],
["Signature"] = token
};
}
else if (type == TwoFactorProviderType.WebAuthn)
2022-08-29 16:06:55 -04:00
{
if (token == null)
{
return null;
}
2022-08-29 16:06:55 -04:00
return JsonSerializer.Deserialize<Dictionary<string, object>>(token);
2022-08-29 16:06:55 -04:00
}
else if (type == TwoFactorProviderType.Email)
2022-08-29 16:06:55 -04:00
{
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
return new Dictionary<string, object> { ["Email"] = token };
}
else if (type == TwoFactorProviderType.YubiKey)
2022-08-29 16:06:55 -04:00
{
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
return new Dictionary<string, object> { ["Nfc"] = (bool)provider.MetaData["Nfc"] };
}
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
return null;
case TwoFactorProviderType.OrganizationDuo:
if (await _organizationDuoWebTokenProvider.CanGenerateTwoFactorTokenAsync(organization))
2022-08-29 16:06:55 -04:00
{
return new Dictionary<string, object>
{
["Host"] = provider.MetaData["Host"],
["Signature"] = await _organizationDuoWebTokenProvider.GenerateAsync(organization, user)
};
}
Defect/PM-1196 - SSO with Email 2FA Flow - Email Required error fixed (#2874) * PM-1196 - Created first draft solution for solving SSO with Email 2FA serverside. Per architectural review discussion, will be replacing OTP use with expiring tokenable implementation in order to decouple the OTP implementation from the need for an auth factor when arriving on the email 2FA screen post SSO. * PM-1196 - Refactored OTP solution to leverage newly created SsoEmail2faSessionTokenable. Working now but some code cleanup required. Might revisit whether or not we still send down email alongside the token or not to make the SendEmailLoginAsync method more streamlined. * PM-1196 - Send down email separately on token rejection b/c of 2FA required so that 2FA Controller send email login can be refactored to be much cleaner with email required. * PM-1196 - Fix lint issues w/ dotnet format. * PM-1196 - More formatting issue fixes. * PM-1196 - Remove unnecessary check as email is required again on TwoFactorEmailRequestModel * PM-1196 - Update SsoEmail2faSessionTokenable to expire after just over 2 min to match client side auth service expiration of 2 min with small buffer. * PM-1196 - Fix lint issue w/ dotnet format. * PM-1196 - Per PR feedback, move CustomTokenRequestValidator constructor param to new line * PM-1196 - Per PR feedback, update ThrowDelayedBadRequestExceptionAsync to return a task so that it can be awaited and so that the calling code can handle any exceptions that occur during its execution * PM-1196 - Per PR feedback, refactor SsoEmail2faSessionTokenable to leverage TimeSpan vs double for token expiration lifetime.
2023-05-04 15:12:03 -04:00
return null;
default:
return null;
}
2022-08-29 16:06:55 -04:00
}
protected async Task<bool> KnownDeviceAsync(User user, ValidatedTokenRequest request) =>
(await GetKnownDeviceAsync(user, request)) != default;
protected async Task<Device> GetKnownDeviceAsync(User user, ValidatedTokenRequest request)
2022-08-29 16:06:55 -04:00
{
if (user == null)
{
return default;
2022-08-29 14:53:16 -04:00
}
return await _deviceRepository.GetByIdentifierAsync(GetDeviceFromRequest(request).Identifier, user.Id);
2022-08-29 16:06:55 -04:00
}
private async Task<Device> SaveDeviceAsync(User user, ValidatedTokenRequest request)
2022-08-29 16:06:55 -04:00
{
var device = GetDeviceFromRequest(request);
if (device != null)
{
var existingDevice = await GetKnownDeviceAsync(user, request);
if (existingDevice == null)
{
device.UserId = user.Id;
await _deviceService.SaveAsync(device);
var now = DateTime.UtcNow;
if (now - user.CreationDate > TimeSpan.FromMinutes(10))
2022-08-29 16:06:55 -04:00
{
var deviceType = device.Type.GetType().GetMember(device.Type.ToString())
.FirstOrDefault()?.GetCustomAttribute<DisplayAttribute>()?.GetName();
if (!_globalSettings.DisableEmailNewDevice)
{
await _mailService.SendNewDeviceLoggedInEmail(user.Email, deviceType, now,
_currentContext.IpAddress);
}
}
return device;
}
return existingDevice;
}
return null;
2022-08-29 16:06:55 -04:00
}
private async Task ResetFailedAuthDetailsAsync(User user)
2022-08-29 16:06:55 -04:00
{
// Early escape if db hit not necessary
if (user == null || user.FailedLoginCount == 0)
{
return;
2022-08-29 14:53:16 -04:00
}
user.FailedLoginCount = 0;
user.RevisionDate = DateTime.UtcNow;
await _userRepository.ReplaceAsync(user);
2022-08-29 16:06:55 -04:00
}
private async Task UpdateFailedAuthDetailsAsync(User user, bool twoFactorInvalid, bool unknownDevice)
2022-08-29 16:06:55 -04:00
{
if (user == null)
2022-08-29 16:06:55 -04:00
{
return;
}
var utcNow = DateTime.UtcNow;
user.FailedLoginCount = ++user.FailedLoginCount;
user.LastFailedLoginDate = user.RevisionDate = utcNow;
await _userRepository.ReplaceAsync(user);
2022-08-29 16:06:55 -04:00
if (ValidateFailedAuthEmailConditions(unknownDevice, user))
{
if (twoFactorInvalid)
{
await _mailService.SendFailedTwoFactorAttemptsEmailAsync(user.Email, utcNow, _currentContext.IpAddress);
}
else
{
await _mailService.SendFailedLoginAttemptsEmailAsync(user.Email, utcNow, _currentContext.IpAddress);
}
}
2022-08-29 16:06:55 -04:00
}
private bool ValidateFailedAuthEmailConditions(bool unknownDevice, User user)
{
var failedLoginCeiling = _globalSettings.Captcha.MaximumFailedLoginAttempts;
var failedLoginCount = user?.FailedLoginCount ?? 0;
return unknownDevice && failedLoginCeiling > 0 && failedLoginCount == failedLoginCeiling;
}
[AC-1070] Enforce master password policy on login (#2714) * [EC-1070] Add API endpoint to retrieve all policies for the current user The additional API endpoint is required to avoid forcing a full sync call before every login for master password policy enforcement on login. * [EC-1070] Add MasterPasswordPolicyData model * [EC-1070] Move PolicyResponseModel to Core project The response model is used by both the Identity and Api projects. * [EC-1070] Supply master password polices as a custom identity token response * [EC-1070] Include master password policies in 2FA token response * [EC-1070] Add response model to verify-password endpoint that includes master password policies * [AC-1070] Introduce MasterPasswordPolicyResponseModel * [AC-1070] Add policy service method to retrieve a user's master password policy * [AC-1070] User new policy service method - Update BaseRequestValidator - Update AccountsController for /verify-password endpoint - Update VerifyMasterPasswordResponseModel to accept MasterPasswordPolicyData * [AC-1070] Cleanup new policy service method - Use User object instead of Guid - Remove TODO message - Use `PolicyRepository.GetManyByTypeApplicableToUserIdAsync` instead of filtering locally * [AC-1070] Cleanup MasterPasswordPolicy models - Remove default values from both models - Add missing `RequireLower` - Fix mismatched properties in `CombineWith` method - Make properties nullable in response model * [AC-1070] Remove now un-used GET /policies endpoint * [AC-1070] Update policy service method to use GetManyByUserIdAsync * [AC-1070] Ensure existing value is not null before comparison * [AC-1070] Remove redundant VerifyMasterPasswordResponse model * [AC-1070] Fix service typo in constructor
2023-04-17 07:35:47 -07:00
private async Task<MasterPasswordPolicyResponseModel> GetMasterPasswordPolicy(User user)
{
// Check current context/cache to see if user is in any organizations, avoids extra DB call if not
var orgs = (await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, user.Id))
.ToList();
if (!orgs.Any())
{
return null;
}
return new MasterPasswordPolicyResponseModel(await _policyService.GetMasterPasswordPolicyForUserAsync(user));
}
}