mirror of
https://github.com/bitwarden/server.git
synced 2025-05-25 21:34:52 -05:00
PM-20532 - SendAccessGrantValidator - WIP
This commit is contained in:
parent
e26b29f70e
commit
c7603e71a5
@ -0,0 +1,85 @@
|
||||
using System.Security.Claims;
|
||||
using Bit.Core.Identity;
|
||||
using Bit.Core.Tools.Repositories;
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Validation;
|
||||
|
||||
namespace Bit.Identity.IdentityServer.RequestValidators;
|
||||
|
||||
// TODO: in real implementation, we would use ideally use Tools provided Send queries for the data we need
|
||||
// instead of directly injecting the send repository here.
|
||||
public class SendAccessGrantValidator(ISendRepository sendRepository) : IExtensionGrantValidator
|
||||
{
|
||||
public const string GrantType = "send_access";
|
||||
|
||||
string IExtensionGrantValidator.GrantType => GrantType;
|
||||
|
||||
public async Task ValidateAsync(ExtensionGrantValidationContext context)
|
||||
{
|
||||
var request = context.Request.Raw;
|
||||
|
||||
var sendId = request.Get("send_id");
|
||||
|
||||
if (string.IsNullOrEmpty(sendId))
|
||||
{
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Invalid request. send_id is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Guid.TryParse(sendId, out var sendIdGuid))
|
||||
{
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Invalid request. send_id is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Look up send by id
|
||||
var send = await sendRepository.GetByIdAsync(sendIdGuid);
|
||||
|
||||
// SendAuthQuery from Tools will return authN type + if a send doesn't exist, then we will add enumeration protection
|
||||
// Only will map to password or email + OTP protected. If user submits password guess for a falsely protected send, then
|
||||
// return invalid password.
|
||||
|
||||
if (send == null)
|
||||
{
|
||||
// TODO: evaluate if adding send enumeration protection is required here as rate limiting is present already on the token endpoint
|
||||
// Yes, it does help with self hosted instances. We will
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Invalid request");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// if send is anon, provide access token
|
||||
if (string.IsNullOrEmpty(send.Password))
|
||||
{
|
||||
// context.Result = new GrantValidationResult(subject: sendId);
|
||||
context.Result = BuildBaseSuccessResult(sendId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Email + OTP - if we generate OTP here, we could run into rate limiting issues with re-hitting this endpoint
|
||||
// We will generate & validate OTP here.
|
||||
|
||||
|
||||
// if send is password protected, check if password is provided and validate if so
|
||||
// if send is email + OTP protected, check if email and OTP are provided and validate if so
|
||||
|
||||
|
||||
context.Result = new GrantValidationResult("send_access", GrantType);
|
||||
}
|
||||
|
||||
private GrantValidationResult BuildBaseSuccessResult(string sendId)
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
// TODO: Add email claim when issuing access token for email + OTP send
|
||||
new Claim(Claims.SendId, sendId),
|
||||
new Claim(Claims.Type, IdentityClientType.Send.ToString())
|
||||
};
|
||||
|
||||
return new GrantValidationResult(
|
||||
subject: sendId,
|
||||
authenticationMethod: GrantType,
|
||||
claims: claims);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user