Generate Auth Files
In auth v1
the
mix phx.gen.auth
generator
didn't exist
so we had to hand-write all the code.
For auth v2
we are using the phx.gen.auth
"generator"
to provide some of the scaffolding
and session management.
see:
hexdocs.pm/phoenix/mix_phx_gen_auth
In your terminal, run th following command:
mix phx.gen.auth Accounts Person people
The generator prompts with the following question:
An authentication system can be created in two different ways:
- Using Phoenix.LiveView (default)
- Using Phoenix.Controller only
Do you want to create a LiveView based authentication system? [Yn]
We answered N
(No)
because we will be adding more advanced auth
* creating priv/repo/migrations/20230226095715_create_people_auth_tables.exs
* creating lib/auth/accounts/person_notifier.ex
* creating lib/auth/accounts/person.ex
* creating lib/auth/accounts/person_token.ex
* creating lib/auth_web/person_auth.ex
* creating test/auth_web/person_auth_test.exs
* creating lib/auth_web/controllers/person_session_controller.ex
* creating test/auth_web/controllers/person_session_controller_test.exs
* creating lib/auth_web/controllers/person_confirmation_html.ex
* creating lib/auth_web/controllers/person_confirmation_html/new.html.heex
* creating lib/auth_web/controllers/person_confirmation_html/edit.html.heex
* creating lib/auth_web/controllers/person_confirmation_controller.ex
* creating test/auth_web/controllers/person_confirmation_controller_test.exs
* creating lib/auth_web/controllers/person_registration_html/new.html.heex
* creating lib/auth_web/controllers/person_registration_controller.ex
* creating test/auth_web/controllers/person_registration_controller_test.exs
* creating lib/auth_web/controllers/person_registration_html.ex
* creating lib/auth_web/controllers/person_reset_password_html.ex
* creating lib/auth_web/controllers/person_reset_password_controller.ex
* creating test/auth_web/controllers/person_reset_password_controller_test.exs
* creating lib/auth_web/controllers/person_reset_password_html/edit.html.heex
* creating lib/auth_web/controllers/person_reset_password_html/new.html.heex
* creating lib/auth_web/controllers/person_session_html.ex
* creating lib/auth_web/controllers/person_session_html/new.html.heex
* creating lib/auth_web/controllers/person_settings_html.ex
* creating lib/auth_web/controllers/person_settings_controller.ex
* creating lib/auth_web/controllers/person_settings_html/edit.html.heex
* creating test/auth_web/controllers/person_settings_controller_test.exs
* creating lib/auth/accounts.ex
* injecting lib/auth/accounts.ex
* creating test/auth/accounts_test.exs
* injecting test/auth/accounts_test.exs
* creating test/support/fixtures/accounts_fixtures.ex
* injecting test/support/fixtures/accounts_fixtures.ex
* injecting test/support/conn_case.ex
* injecting config/test.exs
* injecting mix.exs
* injecting lib/auth_web/router.ex
* injecting lib/auth_web/router.ex - imports
* injecting lib/auth_web/router.ex - plug
* injecting lib/auth_web/components/layouts/root.html.heex
Please re-fetch your dependencies with the following command:
$ mix deps.get
Remember to update your repository by running migrations:
$ mix ecto.migrate
Once you are ready, visit "/people/register"
to create your account and then access "/dev/mailbox" to
see the account confirmation email.
That's a lot of code.
See the git
commit:
90086a8
.
We will use the session management
in our auth
system
and delete
some of the unused code along the way.
Migrate the Schema
When you run:
mix ecto.migrate
You will see the following output:
Generated auth app
15:04:11.168 [info] == Running 20230226095715 Auth.Repo.Migrations.CreatePeopleAuthTables.change/0 forward
15:04:11.173 [info] execute "CREATE EXTENSION IF NOT EXISTS citext"
15:04:11.285 [info] create table people
15:04:11.296 [info] create index people_email_index
15:04:11.297 [info] create table people_tokens
15:04:11.302 [info] create index people_tokens_person_id_index
15:04:11.307 [info] create index people_tokens_context_token_index
15:04:11.310 [info] == Migrated 20230226095715 in 0.1s
Schema
Let's take a quick look at the created database tables.
If you open the auth_dev
database in your Postgres GUI,
e.g:
DBEaver
and view the
ERD
there are only two tables:
Data in people
and people_tokens
tables
By default,
mix phx.gen.auth
does not setup any protection
for personal data in the database.
Email addresses are stored in-the-clear: 🙄
Similarly the people_tokens
table stores email
addresses as plaintext
in the sent_to
column:
This is obviously undesirable. 🙃 This is a privacy/security issue waiting to become a scandal! We will address this swiftly in the following pages.
But first, tests!
Run The Tests
Sadly, the phx.gen.auth
there to be a bunch of routes
hard-coded with the "/user" prefix in the tests
e.g:
test/auth_web/controllers/person_session_controller_test.exs#L15
The generator doesn't respect
the fact that we call them people
when we invoked the command above.
so if you run the tests:
mix test
You will see several warnings:
.warning: no route path for AuthWeb.Router matches "/users/log_out"
test/auth_web/controllers/person_registration_controller_test.exs:40: AuthWeb.PersonRegistrationControllerTest."test POST /people/register creates account and logs the person in"/1
warning: no route path for AuthWeb.Router matches "/users/log_out"
test/auth_web/controllers/person_session_controller_test.exs:40: AuthWeb.PersonSessionControllerTest."test POST /people/log_in logs the person in"/1
warning: no route path for AuthWeb.Router matches "/users/settings"
test/auth_web/controllers/person_session_controller_test.exs:39: AuthWeb.PersonSessionControllerTest."test POST /people/log_in logs the person in"/1
warning: no route path for AuthWeb.Router matches "/users/settings"
test/auth_web/controllers/person_registration_controller_test.exs:39: AuthWeb.PersonRegistrationControllerTest."test POST /people/register creates account and logs the person in"/1
warning: no route path for AuthWeb.Router matches "/users/register"
test/auth_web/controllers/person_session_controller_test.exs:15: AuthWeb.PersonSessionControllerTest."test GET /people/log_in renders log in page"/1
warning: no route path for AuthWeb.Router matches "/users/register"
test/auth_web/controllers/person_registration_controller_test.exs:12: AuthWeb.PersonRegistrationControllerTest."test GET /people/register renders registration page"/1
warning: no route path for AuthWeb.Router matches "/users/log_in"
test/auth_web/controllers/person_registration_controller_test.exs:11: AuthWeb.PersonRegistrationControllerTest."test GET /people/register renders registration page"/1
And ultimately the tests fail:
...............................................................................
Finished in 0.6 seconds (0.4s async, 0.2s sync)
115 tests, 5 failures
This should be a easy to fix.
Perform a find-and-replace for "/users/" to "/people/"
Attempt to re-run the tests:
mix test
Sadly, 4 tests still fail:
1) test POST /people/register creates account and logs the person in (AuthWeb.PersonRegistrationControllerTest)
test/auth_web/controllers/person_registration_controller_test.exs:24
Assertion with =~ failed
code: assert response =~ email
left: "<!DOCTYPE html>\n<html lang=\"en\" style=\"scrollbar-gutter: stable;\">\n <head>\n etc.
etc.
.......................................................................
Finished in 0.5 seconds (0.4s async, 0.1s sync)
115 tests, 4 failures
We're going to have to investigate/update these tests manually.