Skip to content

Update auth demo to include password validation #7472

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

Merged
merged 6 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions packages/auth/demo/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,41 @@
Confirm Password Change
</button>
</form>

<!-- Password Validation -->
<div class="group">Password Validation</div>
<form class="form form-bordered no-submit">
<div class="input-group">
<input type="password" name="password" id="password-validation-password"
class="form-control" placeholder="Password" />
<div class="input-group-btn">
<button class="btn btn-default" type="button" id="password-validation-view-password" aria-label="View password">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
</button>
</div>
</div>
<ul class="list-group" id="password-validation-requirements">
<li class="list-group-item" id="password-validation-meets-min-password-length">
Password must be at least <span id="password-validation-min-length">6</span> characters.
</li>
<li class="list-group-item" id="password-validation-meets-max-password-length">
Password must be at most <span id="password-validation-max-length">4096</span> characters.
</li>
<li class="list-group-item" id="password-validation-contains-lowercase-letter">
Password must contain a lowercase letter.
</li>
<li class="list-group-item" id="password-validation-contains-uppercase-letter">
Password must contain an uppercase letter.
</li>
<li class="list-group-item" id="password-validation-contains-numeric-character">
Password must contain a numeric character.
</li>
<li class="list-group-item" id="password-validation-contains-non-alphanumeric-character">
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>
</li>
</ul>
</form>

<!-- Fetch Sign In Methods -->
<div class="group">Fetch Sign In Methods</div>
<form class="form form-bordered no-submit">
Expand Down
17 changes: 17 additions & 0 deletions packages/auth/demo/public/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ body.user-info-displayed {
border: none;
}

#password-validation-requirements {
margin-top: 20px;
margin-bottom: 0;
display: none;
}

#password-validation-requirements .list-group-item {
display: none;
list-style-type: none;
}

#password-validation-contains-non-alphanumeric-character .tooltip {
font-family: 'Courier New', Courier;
font-size: 1.1em;
letter-spacing: 5px;
}

.logs {
color: #555;
font-family: 'Courier New', Courier;
Expand Down
94 changes: 93 additions & 1 deletion packages/auth/demo/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ import {
getRedirectResult,
browserPopupRedirectResolver,
connectAuthEmulator,
initializeRecaptchaConfig
initializeRecaptchaConfig,
validatePassword
} from '@firebase/auth';

import { config } from './config';
Expand Down Expand Up @@ -493,6 +494,93 @@ function onInitializeRecaptchaConfig() {
initializeRecaptchaConfig(auth);
}

/**
* Updates the displayed validation status for the inputted password.
*/
function onValidatePassword() {
/**
* Updates the displayed status for a requirement.
* @param {string} id The ID of the DOM element displaying the requirement status.
* @param {boolean | undefined} status Whether the requirement is met.
*/
function setRequirementStatus(id, status) {
// Hide the requirement if the status does not include it.
if (status === undefined) {
$(id).hide();
return;
}

if (status) {
$(id).removeClass('list-group-item-danger');
$(id).addClass('list-group-item-success');
} else {
$(id).removeClass('list-group-item-success');
$(id).addClass('list-group-item-danger');
}
$(id).show();
}

const password = $('#password-validation-password').val();
validatePassword(auth, password).then(
status => {
const passwordPolicy = status.passwordPolicy;
const customStrengthOptions = passwordPolicy.customStrengthOptions;

// Only show options required by the password policy.
if (customStrengthOptions.minPasswordLength) {
$('#password-validation-min-length').text(
customStrengthOptions.minPasswordLength
);
}
if (customStrengthOptions.maxPasswordLength) {
$('#password-validation-max-length').text(
customStrengthOptions.maxPasswordLength
);
}
if (customStrengthOptions.containsNonAlphanumericCharacter) {
$('#password-validation-allowed-non-alphanumeric-characters').attr(
'data-original-title',
passwordPolicy.allowedNonAlphanumericCharacters
);
}
Object.keys(status).forEach(requirement => {
if (requirement !== 'passwordPolicy') {
// Get the requirement ID by converting to kebab case.
const requirementIdPrefix = '#password-validation-';
const requirementId =
requirementIdPrefix +
requirement.replace(/[A-Z]/g, match => '-' + match.toLowerCase());

setRequirementStatus(requirementId, status[requirement]);
}
});

$('#password-validation-password').prop('disabled', false);
$('#password-validation-requirements').show();
},
error => {
// Disable the password input and hide the requirements since validation cannot be performed.
if (error.code === `auth/unsupported-password-policy-schema-version`) {
$('#password-validation-password').prop('disabled', true);
}
$('#password-validation-requirements').hide();
onAuthError(error);
}
);
}

/**
* Toggles text visibility for the password validation input field.
*/
function onToggleViewPasswordForValidation() {
const id = '#password-validation-password';
if ($(id).prop('type') === 'password') {
$(id).prop('type', 'text');
} else {
$(id).prop('type', 'password');
}
}

/**
* Signs in with a generic IdP credential.
*/
Expand Down Expand Up @@ -2033,6 +2121,10 @@ function initApp() {
$('#sign-in-anonymously').click(onSignInAnonymously);
$('.set-tenant-id').click(onSetTenantID);
$('#initialize-recaptcha-config').click(onInitializeRecaptchaConfig);
$('#password-validation-password').keyup(onValidatePassword);
$('#password-validation-view-password').click(
onToggleViewPasswordForValidation
);
$('#sign-in-with-generic-idp-credential').click(
onSignInWithGenericIdPCredential
);
Expand Down