@@ -6,14 +6,21 @@ import * as stories from "./input-password.stories.ts";
6
6
7
7
# InputPassword Component
8
8
9
- The ` InputPasswordComponent ` allows a user to enter master password related credentials. On form
10
- submission, the component creates cryptographic properties (` newMasterKey ` ,
11
- ` newServerMasterKeyHash ` , etc.) and emits those properties to the parent (along with the other
12
- values defined in ` PasswordInputResult ` ).
9
+ The ` InputPasswordComponent ` allows a user to enter master password related credentials.
10
+ Specifically, it does the following:
13
11
14
- The component is intended for re-use in different scenarios throughout the application. Therefore it
15
- is mostly presentational and simply emits values rather than acting on them itself. It is the job of
16
- the parent component to act on those values as needed.
12
+ 1 . Displays form fields in the UI
13
+ 2 . Validates form fields
14
+ 3 . Generates cryptographic properties based on the form inputs (e.g. ` newMasterKey ` ,
15
+ ` newServerMasterKeyHash ` , etc.)
16
+ 4 . Emits the generated properties to the parent component
17
+
18
+ The ` InputPasswordComponent ` is central to our set/change password flows. It allows us to keep our
19
+ form UI and validation logic consistent across our many set/change password flows.
20
+
21
+ The component is intended for re-use in different set/change password scenarios throughout the
22
+ application. Therefore it is mostly presentational and simply emits values rather than acting on
23
+ them itself. It is the job of the parent component to act on those values as needed.
17
24
18
25
<br />
19
26
@@ -22,11 +29,13 @@ the parent component to act on those values as needed.
22
29
- [ @Inputs ] ( #inputs )
23
30
- [ @Outputs ] ( #outputs )
24
31
- [ The InputPasswordFlow] ( #the-inputpasswordflow )
32
+ - [ Use Cases] ( #use-cases )
25
33
- [ HTML - Form Fields] ( #html---form-fields )
26
34
- [ TypeScript - Credential Generation] ( #typescript---credential-generation )
27
35
- [ Difference between SetInitialPasswordAccountRegistration and SetInitialPasswordAuthedUser] ( #difference-between-setinitialpasswordaccountregistration-and-setinitialpasswordautheduser )
28
36
- [ Validation] ( #validation )
29
37
- [ Submit Logic] ( #submit-logic )
38
+ - [ Submitting From a Parent Dialog Component] ( #submitting-from-a-parent-dialog-component )
30
39
- [ Example] ( #example )
31
40
32
41
<br />
@@ -37,12 +46,23 @@ the parent component to act on those values as needed.
37
46
38
47
- ` flow ` - the parent component must provide an ` InputPasswordFlow ` , which is used to determine
39
48
which form input elements will be displayed in the UI and which cryptographic keys will be created
40
- and emitted.
41
- - ` email ` - the parent component must provide an email so that the ` InputPasswordComponent ` can
42
- create a master key.
49
+ and emitted. [ Click here] ( #the-inputpasswordflow ) to learn more about the different
50
+ ` InputPasswordFlow ` options.
51
+
52
+ ** Optional (sometimes)**
53
+
54
+ These two ` @Inputs ` are optional on some flows, but required on others. Therefore these ` @Inputs `
55
+ are not marked as ` { required: true } ` , but there _ is_ component logic that ensures (requires) that
56
+ the ` email ` and/or ` userId ` is present in certain flows, while not present in other flows.
57
+
58
+ - ` email ` - allows the ` InputPasswordComponent ` to generate a master key
59
+ - ` userId ` - allows the ` InputPasswordComponent ` to do things like get the user's ` kdfConfig ` ,
60
+ decrypt the user key, and perform validation prior to user a key rotation on the parent
43
61
44
62
** Optional**
45
63
64
+ These ` @Inputs ` are truly optional.
65
+
46
66
- ` loading ` - a boolean used to indicate that the parent component is performing some
47
67
long-running/async operation and that the form should be disabled until the operation is complete.
48
68
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.
57
77
## ` @Output() ` 's
58
78
59
79
- ` onPasswordFormSubmit ` - on form submit, emits a ` PasswordInputResult ` object
80
+ ([ see more below] ( #submit-logic ) ).
60
81
- ` onSecondaryButtonClick ` - on click, emits a notice that the secondary button has been clicked.
61
82
The parent component can listen for this event and take some custom action as needed (go back,
62
83
cancel, logout, etc.)
@@ -66,44 +87,88 @@ the parent component to act on those values as needed.
66
87
## The ` InputPasswordFlow `
67
88
68
89
The ` InputPasswordFlow ` is a crucial and required ` @Input ` that influences both the HTML and the
69
- credential generation logic of the component.
90
+ credential generation logic of the component. It is important for the dev to understand when to use
91
+ each flow.
70
92
71
- < br />
93
+ ### Use Cases
72
94
73
- ### HTML - Form Fields
95
+ ** ` SetInitialPasswordAccountRegistration ` **
74
96
75
- The ` InputPasswordFlow ` determines which form fields get displayed in the UI.
97
+ Used in scenarios where we have no existing user, and thus NO active account ` userId ` :
76
98
77
- ** ` InputPasswordFlow.SetInitialPasswordAccountRegistration ` ** and
78
- ** ` InputPasswordFlow.SetInitialPasswordAuthedUser ` **
99
+ - Standard Account Registration
100
+ - Email Invite Account Registration
101
+ - Trial Initiation Account registration<br /><br />
79
102
80
- - Input: New password
81
- - Input: Confirm new password
82
- - Input: Hint
83
- - Checkbox: Check for breaches
103
+ ** ` SetInitialPasswordAuthedUser ` **
84
104
85
- ** ` InputPasswordFlow.ChangePassword ` **
105
+ Used in scenarios where we do have an existing and authed user, and thus an active account ` userId ` :
86
106
87
- Includes everything above, plus:
107
+ - A "just-in-time" (JIT) provisioned user joins a master password (MP) encryption org and must set
108
+ their initial password
109
+ - A "just-in-time" (JIT) provisioned user joins a trusted device encryption (TDE) org with a
110
+ starting role that requires them to have/set their initial password
111
+ - A note on JIT provisioned user flows:
112
+ - Even though a JIT provisioned user is a brand-new user who was “just” created, we consider
113
+ them to be an “existing authed user” _ from the perspective of the set-password flow_ . This is
114
+ because at the time they set their initial password, their account already exists in the
115
+ database (before setting their password) and they have already authenticated via SSO.
116
+ - The same is not true in the account registration flows above&mdash ; that is, during account
117
+ registration when a user reaches the ` /finish-signup ` or ` /trial-initiation ` page to set their
118
+ initial password, their account does not yet exist in the database, and will only be created
119
+ once they set an initial password.
120
+ - An existing user in a TDE org logs in after the org admin upgraded the user to a role that now
121
+ requires them to have/set their initial password
122
+ - An existing user logs in after their org admin offboarded the org from TDE, and the user must now
123
+ have/set their initial password<br /><br />
88
124
89
- - Input: Current password (as the first element in the UI)
125
+ ** ` ChangePassword ` **
90
126
91
- ** ` InputPasswordFlow.ChangePasswordWithOptionalUserKeyRotation ` **
127
+ Used in scenarios where a we simply want simply offer the user the ability to change their password:
92
128
93
- Includes everything above, plus:
129
+ - User clicks an org email invite link an logs in with their password which does not meet the org's
130
+ policy requirements
131
+ - User logs in with password that does not meet the org's policy requirements
132
+ - User logs in after their password was reset via Account Recovery (and now they must change their
133
+ password)<br /><br />
134
+
135
+ ** ` ChangePasswordWithOptionalUserKeyRotation ` **
136
+
137
+ Used in scenarios where we want to offer users the additional option of rotating their user key:
138
+
139
+ - Account Settings (Web) - change password screen
140
+
141
+ Note that the user key rotation itself does not happen on the ` InputPasswordComponent ` , but rather
142
+ on the parent component. The ` InputPasswordComponent ` simply emits a boolean value that indicates
143
+ whether or not the user key should be rotated.<br /><br />
144
+
145
+ ** ` ChangePasswordDelegation ` **
146
+
147
+ Used in scenarios where one user changes the password for another user's account:
148
+
149
+ - Emergency Access Takeover
150
+ - Account Recovery<br /><br />
151
+
152
+ ### HTML - Form Fields
94
153
95
- - Checkbox: Rotate account encryption key (as the last element in the UI)
154
+ Click through the individual Stories in Storybook to see how the ` InputPassswordFlow ` determines
155
+ which form field UI elements get displayed.
96
156
97
157
<br />
98
158
99
159
### TypeScript - Credential Generation
100
160
101
- - The ` SetInitialPasswordAccountRegistration ` and ` SetInitialPasswordAuthedUser ` flows involve a
102
- user setting their password for the first time. Therefore on submit the component will only
103
- generate new credentials (` newMasterKey ` ) and not current credentials (` currentMasterKey ` ).
104
- - The ` ChangePassword ` and ` ChangePasswordWithOptionalUserKeyRotation ` flows both require the user
105
- to enter a current password along with a new password. Therefore on submit the component will
106
- generate current credentials (` currentMasterKey ` ) along with new credentials (` newMasterKey ` ).
161
+ - ** ` SetInitialPasswordAccountRegistration ` ** and ** ` SetInitialPasswordAuthedUser ` **
162
+ - These flows involve a user setting their password for the first time. Therefore on submit the
163
+ component will only generate new credentials (` newMasterKey ` ) and not current credentials
164
+ (` currentMasterKey ` ).<br /><br />
165
+ - ** ` ChangePassword ` ** and ** ` ChangePasswordWithOptionalUserKeyRotation ` **
166
+ - These flows both require the user to enter a current password along with a new password.
167
+ Therefore on submit the component will generate current credentials (` currentMasterKey ` ) along
168
+ with new credentials (` newMasterKey ` ).<br /><br />
169
+ - ** ` ChangePasswordDelegation ` **
170
+ - This flow does not generate any credentials, but simply validates the new password and emits it
171
+ up to the parent.
107
172
108
173
<br />
109
174
@@ -114,32 +179,8 @@ credentials, but we need to keep them separate for the following reasons:
114
179
115
180
- ` SetInitialPasswordAccountRegistration ` involves scenarios where we have no existing user, and
116
181
** thus NO active account ` userId ` ** :
117
-
118
- - Standard Account Registration
119
- - Email Invite Account Registration
120
- - Trial Initiation Account Registration
121
-
122
- <br />
123
-
124
182
- ` SetInitialPasswordAuthedUser ` involves scenarios where we do have an existing and authed user,
125
183
and ** thus an active account ` userId ` ** :
126
- - A "just-in-time" (JIT) provisioned user joins a master password (MP) encryption org and must set
127
- their initial password
128
- - A "just-in-time" (JIT) provisioned user joins a trusted device encryption (TDE) org with a
129
- starting role that requires them to have/set their initial password
130
- - A note on JIT provisioned user flows:
131
- - Even though a JIT provisioned user is a brand-new user who was “just” created, we consider
132
- them to be an “existing authed user” _ from the perspective of the set-password flow_ . This
133
- is because at the time they set their initial password, their account already exists in the
134
- database (before setting their password) and they have already authenticated via SSO.
135
- - The same is not true in the account registration flows above&mdash ; that is, during account
136
- registration when a user reaches the ` /finish-signup ` or ` /trial-initiation ` page to set
137
- their initial password, their account does not yet exist in the database, and will only be
138
- created once they set an initial password.
139
- - An existing user in a TDE org logs in after the org admin upgraded the user to a role that now
140
- requires them to have/set their initial password
141
- - An existing user logs in after their org admin offboarded the org from TDE, and the user must
142
- now have/set their initial password
143
184
144
185
The presence or absence of an active account ` userId ` is important because it determines how we get
145
186
the correct ` kdfConfig ` prior to key generation:
@@ -170,11 +211,6 @@ Form validators ensure that:
170
211
- The new password and confirmed new password are the same
171
212
- The new password and password hint are NOT the same
172
213
173
- Additional submit logic validation ensures that:
174
-
175
- - The new password adheres to any enforced master password policy options (that were passed down
176
- from the parent)
177
-
178
214
<br />
179
215
180
216
## Submit Logic
@@ -183,9 +219,10 @@ When the form is submitted, the `InputPasswordComponent` does the following in o
183
219
184
220
1 . Verifies inputs:
185
221
- Checks that the current password is correct (if it was required in the flow)
186
- - Checks if the new password is found in a breach and warns the user if so (if the user selected
187
- the checkbox)
188
- - Checks that the new password meets any master password policy requirements enforced by an org
222
+ - Checks that the new password is not weak or found in any breaches (if the user selected the
223
+ checkbox)
224
+ - Checks that the new password adheres to any enforced master password policies that were
225
+ optionally passed down by the parent
189
226
2 . Uses the form inputs to create cryptographic properties (` newMasterKey ` ,
190
227
` newServerMasterKeyHash ` , etc.)
191
228
3 . Emits those cryptographic properties up to the parent (along with other values defined in
@@ -209,6 +246,67 @@ export interface PasswordInputResult {
209
246
}
210
247
```
211
248
249
+ ## Submitting From a Parent Dialog Component
250
+
251
+ Some of our set/change password flows use dialogs, such as Emergency Access Takeover and Account
252
+ Recovery. These are covered by the ` ChangePasswordDelegation ` flow. Because dialogs have their own
253
+ buttons, we don't want to display an additional Submit button in the ` InputPasswordComponent ` when
254
+ embedded a dialog.
255
+
256
+ Therefore we do the following:
257
+
258
+ - The ` InputPasswordComponent ` hides the button in the UI and exposes its ` submit() ` method as a
259
+ public method.
260
+ - The parent dialog component can then access this method via ` @ViewChild() ` .
261
+ - When the user clicks the primary button on the parent dialog, we call the ` submit() ` method on the
262
+ ` InputPasswordComponent ` .
263
+
264
+ ``` html
265
+ <!-- emergency-access-takeover-dialog.component.html -->
266
+
267
+ <bit-dialog dialogSize =" large" >
268
+ <span bitDialogTitle ><!-- ... --> </span >
269
+
270
+ <div bitDialogContent >
271
+ <auth-input-password
272
+ [flow] =" inputPasswordFlow"
273
+ [masterPasswordPolicyOptions] =" masterPasswordPolicyOptions"
274
+ (onPasswordFormSubmit) =" handlePasswordFormSubmit($event)"
275
+ ></auth-input-password >
276
+ </div >
277
+
278
+ <ng-container bitDialogFooter >
279
+ <button type =" button" bitButton buttonType =" primary" (click) =" handlePrimaryButtonClick()" >
280
+ {{ "save" | i18n }}
281
+ </button >
282
+ <button type =" button" bitButton buttonType =" secondary" bitDialogClose >
283
+ {{ "cancel" | i18n }}
284
+ </button >
285
+ </ng-container >
286
+ </bit-dialog >
287
+ ```
288
+
289
+ ``` typescript
290
+ // emergency-access-takeover-dialog.component.ts
291
+
292
+ export class EmergencyAccessTakeoverDialogComponent implements OnInit {
293
+ @ViewChild (InputPasswordComponent )
294
+ inputPasswordComponent: InputPasswordComponent ;
295
+
296
+ // ...
297
+
298
+ handlePrimaryButtonClick = async () => {
299
+ await this .inputPasswordComponent .submit ();
300
+ };
301
+
302
+ async handlePasswordFormSubmit(passwordInputResult : PasswordInputResult ) {
303
+ // ... run logic that handles the `PasswordInputResult` object emission
304
+ }
305
+ }
306
+ ```
307
+
308
+ <br />
309
+
212
310
# Example
213
311
214
312
** ` InputPasswordFlow.ChangePasswordWithOptionalUserKeyRotation ` **
0 commit comments