-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Add UpdateAccountCryptographicState repository function #6669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Claude finished @quexten's task —— View job Code Review CompleteTasks
Overall AssessmentThis PR adds a new repository method for updating user cryptographic state as part of v2 account registration. While the implementation follows Bitwarden patterns and handles transactions correctly, there are critical issues with the test suite that must be addressed before merge. ❌ Critical Issues1. Test Suite Contains Invalid V1 Test CaseFile: The test creates V1 account keys data (without SignatureKeyPairData and SecurityStateData) and attempts to pass it to var accountKeysDataV1 = new UserAccountKeysData
{
PublicKeyEncryptionKeyPairData = new PublicKeyEncryptionKeyPairData(
wrappedPrivateKey: "v1-wrapped-private-key",
publicKey: "v1-public-key"
)
};
await sut.SetV2AccountCryptographicStateAsync(createdUser.Id, accountKeysDataV1);Problem:
Fix Required: Either:
2. Null-Forgiving Operators Risk Runtime ExceptionsFile: SecurityState = accountKeysData.SecurityStateData!.SecurityState,
SecurityVersion = accountKeysData.SecurityStateData!.SecurityVersion,
// ... more null-forgiving operatorsProblem: If Recommendation: Add defensive null checks: if (accountKeysData.SecurityStateData == null || accountKeysData.SignatureKeyPairData == null)
{
throw new InvalidOperationException("V2 encryption data incomplete.");
}
|
|
New Issues (3)Checkmarx found the following issues in this Pull Request
Fixed Issues (6)Great job! The following issues were fixed in this Pull Request
|
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6669 +/- ##
==========================================
+ Coverage 53.65% 57.66% +4.01%
==========================================
Files 1926 1914 -12
Lines 85720 85061 -659
Branches 7687 7610 -77
==========================================
+ Hits 45989 49049 +3060
+ Misses 37958 34177 -3781
- Partials 1773 1835 +62 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
mzieniukbw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not entirely sure whether we can and should use the same command for SSO JIT and master password user registration flows, since in one we update the existing user and in the other we need to create the user with all the keys.
| user.SecurityVersion = accountKeysData.SecurityStateData.SecurityVersion; | ||
| await _userSignatureKeyPairRepository.UpsertAsync(new UserSignatureKeyPair | ||
| { | ||
| Id = CoreHelpers.GenerateComb(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the Id set, this will trigger Update, instead of Create / Insert, is it intended ?
Note: when Id is omitted, upsert would trigger Create and set the Id automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed this to CreateAsync, and added docs clarifying this command should only be used for setting the initial keys, not updating.
src/Core/KeyManagement/Commands/SetAccountKeysForUserCommand.cs
Outdated
Show resolved
Hide resolved
| user.SignedPublicKey = accountKeysData.PublicKeyEncryptionKeyPairData.SignedPublicKey; | ||
| user.SecurityState = accountKeysData.SecurityStateData.SecurityState; | ||
| user.SecurityVersion = accountKeysData.SecurityStateData.SecurityVersion; | ||
| await _userSignatureKeyPairRepository.UpsertAsync(new UserSignatureKeyPair |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we want to use this for user registration for now, it would make sense to call CreateAsync directly.
| var user = await _userRepository.GetByIdAsync(userId); | ||
| if (user == null) | ||
| { | ||
| throw new ArgumentException("User not found", nameof(userId)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this is true for SSO JIT, user registration with master password will not have user created yet (check
| await _registerUserCommand.RegisterUserViaEmailVerificationToken(user, model.MasterPasswordHash, |
Unless the intention is to ensure that user is created first without the keys, and then the keys are updated with this command. Does not feel great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the other comment, I've now updated the comment and the command is now meant for just setting initial keys, so JIT password / regular MP have to find a different solution / write their own command that atomically sets all their data.
|
|
||
| public async Task SetAccountKeysForUserAsync(Guid userId, AccountKeysRequestModel accountKeys) | ||
| { | ||
| var user = await _userRepository.GetByIdAsync(userId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 For the case where user is created, maybe it would make more sense to provide User user instead of Guid ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Updated to take a user. I also added a comment since the user that is passed in does get mutated in the process, which may be unintuitive.
|
|
||
| namespace Bit.Core.KeyManagement.Commands.Interfaces; | ||
|
|
||
| public interface ISetAccountKeysForUserCommand |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some docs would be useful
src/Core/KeyManagement/Commands/SetAccountKeysForUserCommand.cs
Outdated
Show resolved
Hide resolved
08db72c to
e4a8a41
Compare
src/Infrastructure.EntityFramework/Repositories/UserRepository.cs
Outdated
Show resolved
Hide resolved
src/Infrastructure.EntityFramework/Repositories/UserRepository.cs
Outdated
Show resolved
Hide resolved
src/Infrastructure.EntityFramework/Repositories/UserRepository.cs
Outdated
Show resolved
Hide resolved
src/Sql/dbo/Stored Procedures/User_UpdateAccountCryptographicState.sql
Outdated
Show resolved
Hide resolved
src/Infrastructure.EntityFramework/Repositories/UserRepository.cs
Outdated
Show resolved
Hide resolved
mkincaid-bw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM





🎟️ Tracking
📔 Objective
Unblock v2 account registration related tasks.
📸 Screenshots
⏰ Reminders before review
🦮 Reviewer guidelines
:+1:) or similar for great changes:memo:) or ℹ️ (:information_source:) for notes or general info:question:) for questions:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion:art:) for suggestions / improvements:x:) or:warning:) for more significant problems or concerns needing attention:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt:pick:) for minor or nitpick changes