Skip to content

Commit a70a9ac

Browse files
authored
Update auth demo to include password validation (#7472)
* Update auth demo to include a section for password validation
1 parent 5ef98ff commit a70a9ac

File tree

3 files changed

+145
-1
lines changed

3 files changed

+145
-1
lines changed

packages/auth/demo/public/index.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,41 @@
367367
Confirm Password Change
368368
</button>
369369
</form>
370+
371+
<!-- Password Validation -->
372+
<div class="group">Password Validation</div>
373+
<form class="form form-bordered no-submit">
374+
<div class="input-group">
375+
<input type="password" name="password" id="password-validation-password"
376+
class="form-control" placeholder="Password" />
377+
<div class="input-group-btn">
378+
<button class="btn btn-default" type="button" id="password-validation-view-password" aria-label="View password">
379+
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
380+
</button>
381+
</div>
382+
</div>
383+
<ul class="list-group" id="password-validation-requirements">
384+
<li class="list-group-item" id="password-validation-meets-min-password-length">
385+
Password must be at least <span id="password-validation-min-length">6</span> characters.
386+
</li>
387+
<li class="list-group-item" id="password-validation-meets-max-password-length">
388+
Password must be at most <span id="password-validation-max-length">4096</span> characters.
389+
</li>
390+
<li class="list-group-item" id="password-validation-contains-lowercase-letter">
391+
Password must contain a lowercase letter.
392+
</li>
393+
<li class="list-group-item" id="password-validation-contains-uppercase-letter">
394+
Password must contain an uppercase letter.
395+
</li>
396+
<li class="list-group-item" id="password-validation-contains-numeric-character">
397+
Password must contain a numeric character.
398+
</li>
399+
<li class="list-group-item" id="password-validation-contains-non-alphanumeric-character">
400+
Password must contain a non-alphanumeric character. <span class="glyphicon glyphicon-info-sign" id="password-validation-allowed-non-alphanumeric-characters" data-toggle="tooltip" data-placement="bottom" title="No allowed non-alphanumeric characters." aria-label="View non-alphanumeric characters"></span>
401+
</li>
402+
</ul>
403+
</form>
404+
370405
<!-- Fetch Sign In Methods -->
371406
<div class="group">Fetch Sign In Methods</div>
372407
<form class="form form-bordered no-submit">

packages/auth/demo/public/style.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,23 @@ body.user-info-displayed {
7676
border: none;
7777
}
7878

79+
#password-validation-requirements {
80+
margin-top: 20px;
81+
margin-bottom: 0;
82+
display: none;
83+
}
84+
85+
#password-validation-requirements .list-group-item {
86+
display: none;
87+
list-style-type: none;
88+
}
89+
90+
#password-validation-contains-non-alphanumeric-character .tooltip {
91+
font-family: 'Courier New', Courier;
92+
font-size: 1.1em;
93+
letter-spacing: 5px;
94+
}
95+
7996
.logs {
8097
color: #555;
8198
font-family: 'Courier New', Courier;

packages/auth/demo/src/index.js

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ import {
7272
getRedirectResult,
7373
browserPopupRedirectResolver,
7474
connectAuthEmulator,
75-
initializeRecaptchaConfig
75+
initializeRecaptchaConfig,
76+
validatePassword
7677
} from '@firebase/auth';
7778

7879
import { config } from './config';
@@ -493,6 +494,93 @@ function onInitializeRecaptchaConfig() {
493494
initializeRecaptchaConfig(auth);
494495
}
495496

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 | undefined} status Whether the requirement is met.
505+
*/
506+
function setRequirementStatus(id, status) {
507+
// Hide the requirement if the status does not include it.
508+
if (status === undefined) {
509+
$(id).hide();
510+
return;
511+
}
512+
513+
if (status) {
514+
$(id).removeClass('list-group-item-danger');
515+
$(id).addClass('list-group-item-success');
516+
} else {
517+
$(id).removeClass('list-group-item-success');
518+
$(id).addClass('list-group-item-danger');
519+
}
520+
$(id).show();
521+
}
522+
523+
const password = $('#password-validation-password').val();
524+
validatePassword(auth, password).then(
525+
status => {
526+
const passwordPolicy = status.passwordPolicy;
527+
const customStrengthOptions = passwordPolicy.customStrengthOptions;
528+
529+
// Only show options required by the password policy.
530+
if (customStrengthOptions.minPasswordLength) {
531+
$('#password-validation-min-length').text(
532+
customStrengthOptions.minPasswordLength
533+
);
534+
}
535+
if (customStrengthOptions.maxPasswordLength) {
536+
$('#password-validation-max-length').text(
537+
customStrengthOptions.maxPasswordLength
538+
);
539+
}
540+
if (customStrengthOptions.containsNonAlphanumericCharacter) {
541+
$('#password-validation-allowed-non-alphanumeric-characters').attr(
542+
'data-original-title',
543+
passwordPolicy.allowedNonAlphanumericCharacters
544+
);
545+
}
546+
Object.keys(status).forEach(requirement => {
547+
if (requirement !== 'passwordPolicy') {
548+
// Get the requirement ID by converting to kebab case.
549+
const requirementIdPrefix = '#password-validation-';
550+
const requirementId =
551+
requirementIdPrefix +
552+
requirement.replace(/[A-Z]/g, match => '-' + match.toLowerCase());
553+
554+
setRequirementStatus(requirementId, status[requirement]);
555+
}
556+
});
557+
558+
$('#password-validation-password').prop('disabled', false);
559+
$('#password-validation-requirements').show();
560+
},
561+
error => {
562+
// Disable the password input and hide the requirements since validation cannot be performed.
563+
if (error.code === `auth/unsupported-password-policy-schema-version`) {
564+
$('#password-validation-password').prop('disabled', true);
565+
}
566+
$('#password-validation-requirements').hide();
567+
onAuthError(error);
568+
}
569+
);
570+
}
571+
572+
/**
573+
* Toggles text visibility for the password validation input field.
574+
*/
575+
function onToggleViewPasswordForValidation() {
576+
const id = '#password-validation-password';
577+
if ($(id).prop('type') === 'password') {
578+
$(id).prop('type', 'text');
579+
} else {
580+
$(id).prop('type', 'password');
581+
}
582+
}
583+
496584
/**
497585
* Signs in with a generic IdP credential.
498586
*/
@@ -2033,6 +2121,10 @@ function initApp() {
20332121
$('#sign-in-anonymously').click(onSignInAnonymously);
20342122
$('.set-tenant-id').click(onSetTenantID);
20352123
$('#initialize-recaptcha-config').click(onInitializeRecaptchaConfig);
2124+
$('#password-validation-password').keyup(onValidatePassword);
2125+
$('#password-validation-view-password').click(
2126+
onToggleViewPasswordForValidation
2127+
);
20362128
$('#sign-in-with-generic-idp-credential').click(
20372129
onSignInWithGenericIdPCredential
20382130
);

0 commit comments

Comments
 (0)