I initially asked a question here about how to use Solspace Freeform to build a custom front-end login form. I gave up too easily and accepted the "it's possible but probably not a good idea" answer. Full disclosure: I'm still trying to see if I can use Freeform as a replacement for all of the stock Craft front-end forms (login, user profile, entry, etc). There is so much available out of the box with Freeform in terms of form validation rules and styling, I really want to leverage that for all my forms.

  • I have a Freeform login form with the appropriate fields
  • In my custom module, I'm hooking into Freeform's EVENT_FORM_VALIDATE
  • At this point the Craft::$app->request object has everything that the craft\controllers\UsersController's actionLogin() method would need to attempt to log the user in
  • Is there some way to "hand off" the current request to the UsersController?
  • If the login is successful, will the UsersController go about its business and redirect the user properly?
  • If the login fails, I can add errors the Freeform's response as needed
  • Is this a terrible idea? Is there a better way to accomplish this?
  • 1
    "Is this a terrible idea?" ... Maybe not terrible, but relying on a third-party plugin for such critical core functionality is something I'd definitely avoid. As you're finding out, it makes everything a bit more complicated than it needs to be, and you end up tying yourself in knots and coding workarounds on top of workarounds. Not to mention it stymies your ability to upgrade Craft and increases the burden of testing that everything still works. Commented Aug 7, 2020 at 7:52
  • Surely you could have ported the styles/validation over to the custom forms in the time it's taken you to fiddle with this 🤣 I admire your perseverance and genuinely interested to see where you get with this!
    – dmatthams
    Commented Aug 7, 2020 at 8:55
  • I was able to take this a bit further, handing off the request to the actionLogin() method, and if unsuccessful, I could add errors to the response. However, I wasn't able to actually get a successful login; I'm clearly trying to hijack things and the actionLogin() method wasn't intended to be used this way. Oh well, it was a fun exercise. The route I'll end up taking is using the Craft/Yii validation framework to extend validation rules as I need. I appreciate all the input.
    – Garrett
    Commented Aug 8, 2020 at 1:12

2 Answers 2


Based on your goal, I don't recommend taking this approach for the technical debt reasons in my comment, however your actual question is still a valid one. You can call any controller's method from a plugin/module like this:


Is this a terrible idea? Is there a better way to accomplish this?

One thing that makes a great designer/developer is knowing when to say no. It could be done but it's probably not worth it. If you need to ask the question, sometimes you just need to validate your own thoughts.

At the expense of not answering your other questions, I'd say Freeform is great for non-technical, end users who need to create custom forms that may need to change on a whim at some point.

However, I'm just curious as to why you're trying to use it to "reinvent the wheel" for the login/registration fields when Craft itself already has the proper validation and access control checking built in for those?

The great thing about Craft is the CSS is up to you, so I'm not really sure what you're really gaining by doing this?

If you're trying to get the styling to look right, something like Bootstrap, Foundation or Tailwind might be useful.

Your login form is just 2 fields, user and password:

<form method="post" accept-charset="UTF-8">
    {{ csrfInput() }}
    {{ actionInput('users/login') }}

    <h3><label for="loginName">Username or email</label></h3>
    <input id="loginName" type="text" name="loginName"
        value="{{ craft.app.user.rememberedUsername }}">

    <h3><label for="password">Password</label></h3>
    <input id="password" type="password" name="password">

        <input type="checkbox" name="rememberMe" value="1">
        Remember me

    <input type="submit" value="Login">

    {% if errorMessage is defined %}
        <p>{{ errorMessage }}</p>
    {% endif %}

<p><a href="{{ url('forgotpassword') }}">Forget your password?</a></p>

User profile is similar. It's just HTML with with some CMS specific stuff. It may look complicated when you first start but it's really not when you start to break it down.

One other thought I had is you're trying to give CMS authors/editors a way to throw those forms anywhere on the site, similar to how Freeform (or WordPress/Gravity forms) might do it.

That's probably more of a different answer, but one way to pull that off would be with a custom field such as a dropdown and some Twig templates to see which form the user selected. Then embed the appropriate form using Twig {% include %} for example.


I didn't even touch on Entry forms or User Profile but these are just as straightforward to code and setup. And you can always reuse code on other projects including any custom validators you setup.

I guess my point is if you're going to down the path of a custom module to hook into Freeform anyway, why not just cut out the middleman?

  • Thanks for the thoughtful answer. If you simply consider the login form, then yes Freeform seems overkill. But I have other forms I need to create on the frontend (for editing entries, user profile, registration, etc.) and I have custom user profile fields that I want to validate server side. And Freeform has the ability to build that validation easily in the backend and display it consistently on the frontend. From what I can tell, I'll have to build custom validation logic in order to have Craft do the validation on the server side. But, you're probably right: not worth contorting Freeform.
    – Garrett
    Commented Aug 7, 2020 at 22:03
  • I'm still totally going to try using Craft::$app->runAction('users/sogin') to see what happens!
    – Garrett
    Commented Aug 7, 2020 at 22:04
  • I've updated my answer with links to Craft's docs on Entries and User Profile. I guess my point is if you're going to down the path of a custom module to hook into Freeform anyway, why not just cut out the middleman? Commented Aug 8, 2020 at 19:50

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.