2

While logged into the Control Panel, you can edit your account information. When you try to change your email address or password, Craft asks you to enter your current password (for security reasons).

Is it possible to borrow this password confirmation security feature?

I've built a form which is very powerful and contains sensitive data. I want the user to be triple-sure that they want to submit the form... Forcing users to re-enter their password seems like a good way to minimize accidents.

enter image description here

2
  • I'm not sure, but I do see the javascript function that controls this in AccountSettingsForm.js line 12 - Craft.AccountSettingsForm showCurrentPasswordForm. I don't see why you couldn't replicate this. I would like to use this also. Commented Oct 19, 2014 at 19:52
  • Looking at the js class a little closer it looks like the init and showCurrentPasswordForm methods are pretty generic and would work as-is, however, submitCurrentPassword success clause is tied to the email and password fields specifically and would need to be rewritten. It would be nice to write something generic that could be applied anywhere. Commented Oct 19, 2014 at 20:08

1 Answer 1

1

I copied and modified the built-in craft AccountSettingsForm.js and placed it in my own plugin to test and it seems to work great. You will need to adapt it for your own use of course. It is currently triggered on elements that have a class 'btn confirm', and just prints 'Password Confirmed!' on success to the alert window.

Create a button in your plugins CP template file:

<input type="submit" class="btn confirm small submit" value="{{ 'Confirm'|t }}" >

And include the new js file PasswordConfirmation.js, which is:

(function($) {

PasswordConfirmation = Garnish.Base.extend(
{
    isCurrent: null,

    $lockBtns: null,
    $currentPasswordInput: null,
    $spinner: null,

    modal: null,

    init: function(isCurrent)
    {
        this.isCurrent = isCurrent;
        this.$lockBtns = $('.btn.confirm');
        this.addListener(this.$lockBtns, 'click', 'showCurrentPasswordForm');
    },

    showCurrentPasswordForm: function()
    {
        if (!this.modal)
        {
            var $form = $('<form id="verifypasswordmodal" class="modal fitted"/>').appendTo(Garnish.$bod),
                $body = $('<div class="body"><p>'+Craft.t(this.isCurrent ? 'Please enter your current password.' : 'Please enter your password.')+'</p></div>').appendTo($form),
                $passwordWrapper = $('<div class="passwordwrapper"/>').appendTo($body),
                $buttons = $('<div class="buttons right"/>').appendTo($body),
                $cancelBtn = $('<div class="btn">'+Craft.t('Cancel')+'</div>').appendTo($buttons),
                $submitBtn = $('<input type="submit" class="btn submit" value="'+Craft.t('Continue')+'" />').appendTo($buttons);

            this.$currentPasswordInput = $('<input type="password" class="text password fullwidth"/>').appendTo($passwordWrapper);
            this.$spinner = $('<div class="spinner hidden"/>').appendTo($buttons);
            this.modal = new Garnish.Modal($form);

            new Craft.PasswordInput(this.$currentPasswordInput, {
                onToggleInput: $.proxy(function($newPasswordInput) {
                    this.$currentPasswordInput = $newPasswordInput;
                }, this)
            });

            this.addListener($cancelBtn, 'click', function() {
                this.modal.hide();
            });

            this.addListener($form, 'submit', 'submitCurrentPassword');
        }
        else
        {
            this.modal.show();
        }

        // Auto-focus the password input
        if (!Garnish.isMobileBrowser(true))
        {
            setTimeout($.proxy(function() {
                this.$currentPasswordInput.focus();
            }, this), 100);
        }
    },

    submitCurrentPassword: function(ev)
    {
        ev.preventDefault();

        var password = this.$currentPasswordInput.val();

        if (password)
        {
            this.$spinner.removeClass('hidden');

            var data = {
                password: password
            };

            Craft.postActionRequest('users/verifyPassword', data, $.proxy(function(response, textStatus)
            {
                this.$spinner.addClass('hidden');

                if (textStatus == 'success')
                {
                    if (response.success)
                    {
                        alert('Password Confirmed!');

                        this.modal.hide();

                    }
                    else
                    {
                        Garnish.shake(this.modal.$container);
                    }
                }

            }, this));
        }
    }

});

new PasswordConfirmation;

})(jQuery)

The next step would be to make it more generic so that it returns true, or executes a callback method, so that the result function can be customized per-use, and perhaps improve the instantiation so that you can pass it your own jquery selectors.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.