@@ -72,7 +72,8 @@ import {
72
72
getRedirectResult ,
73
73
browserPopupRedirectResolver ,
74
74
connectAuthEmulator ,
75
- initializeRecaptchaConfig
75
+ initializeRecaptchaConfig ,
76
+ validatePassword
76
77
} from '@firebase/auth' ;
77
78
78
79
import { config } from './config' ;
@@ -493,6 +494,87 @@ function onInitializeRecaptchaConfig() {
493
494
initializeRecaptchaConfig ( auth ) ;
494
495
}
495
496
497
+ /**
498
+ * Updates the displayed validation status for the inputted password.
499
+ */
500
+ function onValidatePassword ( ) {
501
+ /**
502
+ * Updates the displayed status for a requirement.
503
+ * @param {string } id The ID of the DOM element displaying the requirement status.
504
+ * @param {boolean } status Whether the requirement is met.
505
+ */
506
+ function setRequirementStatus ( id , status ) {
507
+ if ( status ) {
508
+ $ ( id ) . removeClass ( 'list-group-item-danger' ) ;
509
+ $ ( id ) . addClass ( 'list-group-item-success' ) ;
510
+ } else {
511
+ $ ( id ) . removeClass ( 'list-group-item-success' ) ;
512
+ $ ( id ) . addClass ( 'list-group-item-danger' ) ;
513
+ }
514
+ $ ( id ) . show ( ) ;
515
+ }
516
+
517
+ const password = $ ( '#password-validation-password' ) . val ( ) ;
518
+ validatePassword ( auth , password ) . then (
519
+ status => {
520
+ const customStrengthOptions = status . passwordPolicy . customStrengthOptions ;
521
+
522
+ // Only show options required by the password policy.
523
+ if ( customStrengthOptions . minPasswordLength ) {
524
+ $ ( '#password-validation-min-length' ) . text (
525
+ customStrengthOptions . minPasswordLength
526
+ ) ;
527
+ setRequirementStatus (
528
+ '#password-validation-meets-min-length' ,
529
+ status . meetsMinPasswordLength
530
+ ) ;
531
+ }
532
+ if ( customStrengthOptions . maxPasswordLength ) {
533
+ $ ( '#password-validation-max-length' ) . text (
534
+ customStrengthOptions . maxPasswordLength
535
+ ) ;
536
+ setRequirementStatus (
537
+ '#password-validation-meets-max-length' ,
538
+ status . meetsMaxPasswordLength
539
+ ) ;
540
+ }
541
+ if ( customStrengthOptions . containsLowercaseLetter ) {
542
+ setRequirementStatus (
543
+ '#password-validation-contains-lowercase' ,
544
+ status . containsLowercaseLetter
545
+ ) ;
546
+ }
547
+ if ( customStrengthOptions . containsUppercaseLetter ) {
548
+ setRequirementStatus (
549
+ '#password-validation-contains-uppercase' ,
550
+ status . containsUppercaseLetter
551
+ ) ;
552
+ }
553
+ if ( customStrengthOptions . containsNumericCharacter ) {
554
+ setRequirementStatus (
555
+ '#password-validation-contains-numeric' ,
556
+ status . containsNumericCharacter
557
+ ) ;
558
+ }
559
+ if ( customStrengthOptions . containsNonAlphanumericCharacter ) {
560
+ setRequirementStatus (
561
+ '#password-validation-contains-non-alphanumeric' ,
562
+ status . containsNonAlphanumericCharacter
563
+ ) ;
564
+ }
565
+
566
+ $ ( '#password-validation-password' ) . prop ( 'disabled' , false ) ;
567
+ $ ( '#password-validation-requirements' ) . show ( ) ;
568
+ } ,
569
+ error => {
570
+ // Disable the password input and hide the requirements since validation cannot be performed.
571
+ $ ( '#password-validation-password' ) . prop ( 'disabled' , true ) ;
572
+ $ ( '#password-validation-requirements' ) . hide ( ) ;
573
+ onAuthError ( error ) ;
574
+ }
575
+ ) ;
576
+ }
577
+
496
578
/**
497
579
* Signs in with a generic IdP credential.
498
580
*/
@@ -2033,6 +2115,7 @@ function initApp() {
2033
2115
$ ( '#sign-in-anonymously' ) . click ( onSignInAnonymously ) ;
2034
2116
$ ( '.set-tenant-id' ) . click ( onSetTenantID ) ;
2035
2117
$ ( '#initialize-recaptcha-config' ) . click ( onInitializeRecaptchaConfig ) ;
2118
+ $ ( '#password-validation-password' ) . keyup ( onValidatePassword ) ;
2036
2119
$ ( '#sign-in-with-generic-idp-credential' ) . click (
2037
2120
onSignInWithGenericIdPCredential
2038
2121
) ;
0 commit comments