mirror of
https://github.com/bitwarden/server.git
synced 2026-02-06 17:13:10 +08:00
[PM-8220] New Device Verification (#5084)
* feat(BaseRequestValidator): Add global setting for new device verification. Refactor BaseRequestValidator enabling better self-documenting code and better single responsibility principle for validators. Updated DeviceValidator to handle new device verification, behind a feature flag. Moved IDeviceValidator interface to separate file. Updated CustomRequestValidator to act as the conduit by which *Validators communicate authentication context between themselves and the RequestValidators. Adding new test for DeviceValidator class. Updated tests for BaseRequestValidator as some functionality was moved to the DeviceValidator class.
This commit is contained in:
@@ -75,11 +75,16 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
|
||||
}
|
||||
|
||||
var user = await _userManager.FindByEmailAsync(context.UserName.ToLowerInvariant());
|
||||
// We want to keep this device around incase the device is new for the user
|
||||
var requestDevice = DeviceValidator.GetDeviceFromRequest(context.Request);
|
||||
var knownDevice = await _deviceValidator.GetKnownDeviceAsync(user, requestDevice);
|
||||
var validatorContext = new CustomValidatorRequestContext
|
||||
{
|
||||
User = user,
|
||||
KnownDevice = await _deviceValidator.KnownDeviceAsync(user, context.Request),
|
||||
KnownDevice = knownDevice != null,
|
||||
Device = knownDevice ?? requestDevice,
|
||||
};
|
||||
|
||||
string bypassToken = null;
|
||||
if (!validatorContext.KnownDevice &&
|
||||
_captchaValidationService.RequireCaptchaValidation(_currentContext, user))
|
||||
@@ -156,6 +161,7 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Obsolete("Consider using SetGrantValidationErrorResult instead.")]
|
||||
protected override void SetTwoFactorResult(ResourceOwnerPasswordValidationContext context,
|
||||
Dictionary<string, object> customResponse)
|
||||
{
|
||||
@@ -163,6 +169,7 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
|
||||
customResponse);
|
||||
}
|
||||
|
||||
[Obsolete("Consider using SetGrantValidationErrorResult instead.")]
|
||||
protected override void SetSsoResult(ResourceOwnerPasswordValidationContext context,
|
||||
Dictionary<string, object> customResponse)
|
||||
{
|
||||
@@ -170,12 +177,25 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
|
||||
customResponse);
|
||||
}
|
||||
|
||||
[Obsolete("Consider using SetGrantValidationErrorResult instead.")]
|
||||
protected override void SetErrorResult(ResourceOwnerPasswordValidationContext context,
|
||||
Dictionary<string, object> customResponse)
|
||||
{
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, customResponse: customResponse);
|
||||
}
|
||||
|
||||
protected override void SetValidationErrorResult(
|
||||
ResourceOwnerPasswordValidationContext context, CustomValidatorRequestContext requestContext)
|
||||
{
|
||||
context.Result = new GrantValidationResult
|
||||
{
|
||||
Error = requestContext.ValidationErrorResult.Error,
|
||||
ErrorDescription = requestContext.ValidationErrorResult.ErrorDescription,
|
||||
IsError = true,
|
||||
CustomResponse = requestContext.CustomResponse
|
||||
};
|
||||
}
|
||||
|
||||
protected override ClaimsPrincipal GetSubject(ResourceOwnerPasswordValidationContext context)
|
||||
{
|
||||
return context.Result.Subject;
|
||||
@@ -183,28 +203,26 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator<ResourceOwner
|
||||
|
||||
private bool AuthEmailHeaderIsValid(ResourceOwnerPasswordValidationContext context)
|
||||
{
|
||||
if (!_currentContext.HttpContext.Request.Headers.ContainsKey("Auth-Email"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (_currentContext.HttpContext.Request.Headers.TryGetValue("Auth-Email", out var authEmailHeader))
|
||||
{
|
||||
try
|
||||
{
|
||||
var authEmailHeader = _currentContext.HttpContext.Request.Headers["Auth-Email"];
|
||||
var authEmailDecoded = CoreHelpers.Base64UrlDecodeString(authEmailHeader);
|
||||
|
||||
if (authEmailDecoded != context.UserName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (System.Exception e) when (e is System.InvalidOperationException || e is System.FormatException)
|
||||
catch (Exception e) when (e is InvalidOperationException || e is FormatException)
|
||||
{
|
||||
// Invalid B64 encoding
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user