From 7d1edb99997022f38760f5fd4d012a35b5234402 Mon Sep 17 00:00:00 2001
From: rr-bw <102181210+rr-bw@users.noreply.github.com>
Date: Thu, 8 May 2025 10:04:24 -0700
Subject: [PATCH] [PM-18721] update storybook docs
---
.../angular/input-password/input-password.mdx | 240 ++++++++++++------
1 file changed, 169 insertions(+), 71 deletions(-)
diff --git a/libs/auth/src/angular/input-password/input-password.mdx b/libs/auth/src/angular/input-password/input-password.mdx
index 77542718f4c..384d6b2bc3d 100644
--- a/libs/auth/src/angular/input-password/input-password.mdx
+++ b/libs/auth/src/angular/input-password/input-password.mdx
@@ -6,14 +6,21 @@ import * as stories from "./input-password.stories.ts";
# InputPassword Component
-The `InputPasswordComponent` allows a user to enter master password related credentials. On form
-submission, the component creates cryptographic properties (`newMasterKey`,
-`newServerMasterKeyHash`, etc.) and emits those properties to the parent (along with the other
-values defined in `PasswordInputResult`).
+The `InputPasswordComponent` allows a user to enter master password related credentials.
+Specifically, it does the following:
-The component is intended for re-use in different scenarios throughout the application. Therefore it
-is mostly presentational and simply emits values rather than acting on them itself. It is the job of
-the parent component to act on those values as needed.
+1. Displays form fields in the UI
+2. Validates form fields
+3. Generates cryptographic properties based on the form inputs (e.g. `newMasterKey`,
+ `newServerMasterKeyHash`, etc.)
+4. Emits the generated properties to the parent component
+
+The `InputPasswordComponent` is central to our set/change password flows. It allows us to keep our
+form UI and validation logic consistent across our many set/change password flows.
+
+The component is intended for re-use in different set/change password scenarios throughout the
+application. Therefore it is mostly presentational and simply emits values rather than acting on
+them itself. It is the job of the parent component to act on those values as needed.
@@ -22,11 +29,13 @@ the parent component to act on those values as needed.
- [@Inputs](#inputs)
- [@Outputs](#outputs)
- [The InputPasswordFlow](#the-inputpasswordflow)
+ - [Use Cases](#use-cases)
- [HTML - Form Fields](#html---form-fields)
- [TypeScript - Credential Generation](#typescript---credential-generation)
- [Difference between SetInitialPasswordAccountRegistration and SetInitialPasswordAuthedUser](#difference-between-setinitialpasswordaccountregistration-and-setinitialpasswordautheduser)
- [Validation](#validation)
- [Submit Logic](#submit-logic)
+- [Submitting From a Parent Dialog Component](#submitting-from-a-parent-dialog-component)
- [Example](#example)
@@ -37,12 +46,23 @@ the parent component to act on those values as needed.
- `flow` - the parent component must provide an `InputPasswordFlow`, which is used to determine
which form input elements will be displayed in the UI and which cryptographic keys will be created
- and emitted.
-- `email` - the parent component must provide an email so that the `InputPasswordComponent` can
- create a master key.
+ and emitted. [Click here](#the-inputpasswordflow) to learn more about the different
+ `InputPasswordFlow` options.
+
+**Optional (sometimes)**
+
+These two `@Inputs` are optional on some flows, but required on others. Therefore these `@Inputs`
+are not marked as `{ required: true }`, but there _is_ component logic that ensures (requires) that
+the `email` and/or `userId` is present in certain flows, while not present in other flows.
+
+- `email` - allows the `InputPasswordComponent` to generate a master key
+- `userId` - allows the `InputPasswordComponent` to do things like get the user's `kdfConfig`,
+ decrypt the user key, and perform validation prior to user a key rotation on the parent
**Optional**
+These `@Inputs` are truly optional.
+
- `loading` - a boolean used to indicate that the parent component is performing some
long-running/async operation and that the form should be disabled until the operation is complete.
The primary button will also show a spinner if `loading` is true.
@@ -57,6 +77,7 @@ the parent component to act on those values as needed.
## `@Output()`'s
- `onPasswordFormSubmit` - on form submit, emits a `PasswordInputResult` object
+ ([see more below](#submit-logic)).
- `onSecondaryButtonClick` - on click, emits a notice that the secondary button has been clicked.
The parent component can listen for this event and take some custom action as needed (go back,
cancel, logout, etc.)
@@ -66,44 +87,88 @@ the parent component to act on those values as needed.
## The `InputPasswordFlow`
The `InputPasswordFlow` is a crucial and required `@Input` that influences both the HTML and the
-credential generation logic of the component.
+credential generation logic of the component. It is important for the dev to understand when to use
+each flow.
-
+### Use Cases
+
+**`SetInitialPasswordAccountRegistration`**
+
+Used in scenarios where we have no existing user, and thus NO active account `userId`:
+
+- Standard Account Registration
+- Email Invite Account Registration
+- Trial Initiation Account registration
+
+**`SetInitialPasswordAuthedUser`**
+
+Used in scenarios where we do have an existing and authed user, and thus an active account `userId`:
+
+- A "just-in-time" (JIT) provisioned user joins a master password (MP) encryption org and must set
+ their initial password
+- A "just-in-time" (JIT) provisioned user joins a trusted device encryption (TDE) org with a
+ starting role that requires them to have/set their initial password
+ - A note on JIT provisioned user flows:
+ - Even though a JIT provisioned user is a brand-new user who was “just” created, we consider
+ them to be an “existing authed user” _from the perspective of the set-password flow_. This is
+ because at the time they set their initial password, their account already exists in the
+ database (before setting their password) and they have already authenticated via SSO.
+ - The same is not true in the account registration flows above—that is, during account
+ registration when a user reaches the `/finish-signup` or `/trial-initiation` page to set their
+ initial password, their account does not yet exist in the database, and will only be created
+ once they set an initial password.
+- An existing user in a TDE org logs in after the org admin upgraded the user to a role that now
+ requires them to have/set their initial password
+- An existing user logs in after their org admin offboarded the org from TDE, and the user must now
+ have/set their initial password
+
+**`ChangePassword`**
+
+Used in scenarios where a we simply want simply offer the user the ability to change their password:
+
+- User clicks an org email invite link an logs in with their password which does not meet the org's
+ policy requirements
+- User logs in with password that does not meet the org's policy requirements
+- User logs in after their password was reset via Account Recovery (and now they must change their
+ password)
+
+**`ChangePasswordWithOptionalUserKeyRotation`**
+
+Used in scenarios where we want to offer users the additional option of rotating their user key:
+
+- Account Settings (Web) - change password screen
+
+Note that the user key rotation itself does not happen on the `InputPasswordComponent`, but rather
+on the parent component. The `InputPasswordComponent` simply emits a boolean value that indicates
+whether or not the user key should be rotated.
+
+**`ChangePasswordDelegation`**
+
+Used in scenarios where one user changes the password for another user's account:
+
+- Emergency Access Takeover
+- Account Recovery
### HTML - Form Fields
-The `InputPasswordFlow` determines which form fields get displayed in the UI.
-
-**`InputPasswordFlow.SetInitialPasswordAccountRegistration`** and
-**`InputPasswordFlow.SetInitialPasswordAuthedUser`**
-
-- Input: New password
-- Input: Confirm new password
-- Input: Hint
-- Checkbox: Check for breaches
-
-**`InputPasswordFlow.ChangePassword`**
-
-Includes everything above, plus:
-
-- Input: Current password (as the first element in the UI)
-
-**`InputPasswordFlow.ChangePasswordWithOptionalUserKeyRotation`**
-
-Includes everything above, plus:
-
-- Checkbox: Rotate account encryption key (as the last element in the UI)
+Click through the individual Stories in Storybook to see how the `InputPassswordFlow` determines
+which form field UI elements get displayed.
### TypeScript - Credential Generation
-- The `SetInitialPasswordAccountRegistration` and `SetInitialPasswordAuthedUser` flows involve a
- user setting their password for the first time. Therefore on submit the component will only
- generate new credentials (`newMasterKey`) and not current credentials (`currentMasterKey`).
-- The `ChangePassword` and `ChangePasswordWithOptionalUserKeyRotation` flows both require the user
- to enter a current password along with a new password. Therefore on submit the component will
- generate current credentials (`currentMasterKey`) along with new credentials (`newMasterKey`).
+- **`SetInitialPasswordAccountRegistration`** and **`SetInitialPasswordAuthedUser`**
+ - These flows involve a user setting their password for the first time. Therefore on submit the
+ component will only generate new credentials (`newMasterKey`) and not current credentials
+ (`currentMasterKey`).
+- **`ChangePassword`** and **`ChangePasswordWithOptionalUserKeyRotation`**
+ - These flows both require the user to enter a current password along with a new password.
+ Therefore on submit the component will generate current credentials (`currentMasterKey`) along
+ with new credentials (`newMasterKey`).
+- **`ChangePasswordDelegation`**
+ - This flow does not generate any credentials, but simply validates the new password and emits it
+ up to the parent.
@@ -114,32 +179,8 @@ credentials, but we need to keep them separate for the following reasons:
- `SetInitialPasswordAccountRegistration` involves scenarios where we have no existing user, and
**thus NO active account `userId`**:
-
- - Standard Account Registration
- - Email Invite Account Registration
- - Trial Initiation Account Registration
-
-
-
- `SetInitialPasswordAuthedUser` involves scenarios where we do have an existing and authed user,
and **thus an active account `userId`**:
- - A "just-in-time" (JIT) provisioned user joins a master password (MP) encryption org and must set
- their initial password
- - A "just-in-time" (JIT) provisioned user joins a trusted device encryption (TDE) org with a
- starting role that requires them to have/set their initial password
- - A note on JIT provisioned user flows:
- - Even though a JIT provisioned user is a brand-new user who was “just” created, we consider
- them to be an “existing authed user” _from the perspective of the set-password flow_. This
- is because at the time they set their initial password, their account already exists in the
- database (before setting their password) and they have already authenticated via SSO.
- - The same is not true in the account registration flows above—that is, during account
- registration when a user reaches the `/finish-signup` or `/trial-initiation` page to set
- their initial password, their account does not yet exist in the database, and will only be
- created once they set an initial password.
- - An existing user in a TDE org logs in after the org admin upgraded the user to a role that now
- requires them to have/set their initial password
- - An existing user logs in after their org admin offboarded the org from TDE, and the user must
- now have/set their initial password
The presence or absence of an active account `userId` is important because it determines how we get
the correct `kdfConfig` prior to key generation:
@@ -170,11 +211,6 @@ Form validators ensure that:
- The new password and confirmed new password are the same
- The new password and password hint are NOT the same
-Additional submit logic validation ensures that:
-
-- The new password adheres to any enforced master password policy options (that were passed down
- from the parent)
-
## Submit Logic
@@ -183,9 +219,10 @@ When the form is submitted, the `InputPasswordComponent` does the following in o
1. Verifies inputs:
- Checks that the current password is correct (if it was required in the flow)
- - Checks if the new password is found in a breach and warns the user if so (if the user selected
- the checkbox)
- - Checks that the new password meets any master password policy requirements enforced by an org
+ - Checks that the new password is not weak or found in any breaches (if the user selected the
+ checkbox)
+ - Checks that the new password adheres to any enforced master password policies that were
+ optionally passed down by the parent
2. Uses the form inputs to create cryptographic properties (`newMasterKey`,
`newServerMasterKeyHash`, etc.)
3. Emits those cryptographic properties up to the parent (along with other values defined in
@@ -209,6 +246,67 @@ export interface PasswordInputResult {
}
```
+## Submitting From a Parent Dialog Component
+
+Some of our set/change password flows use dialogs, such as Emergency Access Takeover and Account
+Recovery. These are covered by the `ChangePasswordDelegation` flow. Because dialogs have their own
+buttons, we don't want to display an additional Submit button in the `InputPasswordComponent` when
+embedded a dialog.
+
+Therefore we do the following:
+
+- The `InputPasswordComponent` hides the button in the UI and exposes its `submit()` method as a
+ public method.
+- The parent dialog component can then access this method via `@ViewChild()`.
+- When the user clicks the primary button on the parent dialog, we call the `submit()` method on the
+ `InputPasswordComponent`.
+
+```html
+
+
+
+
+
+