One way to do this is to create a form that you let anonymous users read/write access to. This form will capture email address, username, passwords, etc. Then you can run a microflow that takes object from the form and creates an Account object from that. From there you can show the page with the login form widget and they will be able to log into the application.
To summarize, on your page with the login form, you can add a button to register as a new user. When that button is clicked, you display a form that anonymous users have access too. When they click submit on that form, thats when you create the account object and then display the login form again so they can log into the application.
If you dont want them to have to log in after they create their account, then you can look at this blog post.
Hope this helps!
Edit: I just remembered the forgot password module has an example of this. If you download the module, the snippet called "LoginSnippet" has a sign up button that takes care of everything.
I had the same problem a couple of days ago. You first need to create a temporary entity (give access to anonymous) to store all information from the input fields. This could be a non-persistable one; e.g. AnonymousUser, with attributes like name, email, etc..
After everything has been filled out, you create a button that says “create account” and is linked to a microflow. This microflow creates the object Account and AccountPasswordData first. Then you grab the final bits of information (retrieve) you need: system. user_role ([id = '[%UserRole_THEONEYOUWANT%]']) and language ($currentUser/User_Language) → now change the just created NewAccount and use all the data you have collected in the AnonymousUser object.
This is also described in more detail in: https://gettingstarted.mendixcloud.com/link/module/147/lecture/1170
Hope this helps you.