3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Phoenix 認証システム - mix phx.gen.auth

Last updated at Posted at 2022-10-21

Phoenix では mix phx.gen.auth で、簡単に認証システムを作成し、既存システムに組み込んでいけます。この記事ではどのような認証システムが作成され、どのように利用できるのかを見ていきたいと思います。
mix phx.gen.auth ドキュメント

インターネット創世記の、昔々、ブログシステムを運営していた経緯から、PHPやNodejs、Meteor、Django、AWS JavaScriptなどでWebアプリを実験するときは、必ず認証システムを作成してました。もちろんちょっと前のPhoenixでもそうでした。それで言語・フレームワークの使い易さを計っていました。それが今では mix phx.gen.auth コマンド一発で可能なのはちょっと感動的です。

【関連記事】
Phoenix で Blog を超簡単に作る - phx.gen.auth , phx.gen.html
Phoenix 認証システム - mix phx.gen.auth
Phoenix LiveViewの基本設定 - mix phx.gen.schema
Phoenix1.6の基本的な仕組み - mix phx.gen.html
Elixir/Phoenix のシンプル認証 auth_plug

1.前準備

プロジェクトを作成します。

 mix phx.new auth_test
cd auth_test

以下のコマンドを発行します。Accounts context moduleAccounts.User schema module 、最後に schema moduleの複数形で users tableが作成されます。さらに認証システムに必要なファイル一式が生成されます。

mix phx.gen.auth Accounts User users

以下のコマンドで生成されたファイルの設定を行います。

mix deps.get
mix ecto.setup

以上で前準備が整いました。

2. 認証システムにページを組み込む

phx.gen.auth で生成した認証システムに、新たに生成したページを router.ex 組み込み、どのように認証システムが働くかを確認します。router.ex には以下のような plugs が作成され追加されています。

  • fetch_current_user - 可能ならば current user の情報を取得する
  • require_authenticated_user - fetch_current_user で取得した user が存在し、認証されている必要がある
  • redirect_if_user_is_authenticated - 認証済の user は利用できないページである

それぞれの定義は以下の user_auth.ex で確認できます。

lib/auth_test_web/controllers/user_auth.ex
  ---
  @doc """
  Authenticates the user by looking into the session
  and remember me token.
  """
  def fetch_current_user(conn, _opts) do
    {user_token, conn} = ensure_user_token(conn)
    user = user_token && Accounts.get_user_by_session_token(user_token)
    assign(conn, :current_user, user)
  end

  defp ensure_user_token(conn) do
    if user_token = get_session(conn, :user_token) do
      {user_token, conn}
    else
      conn = fetch_cookies(conn, signed: [@remember_me_cookie])

      if user_token = conn.cookies[@remember_me_cookie] do
        {user_token, put_session(conn, :user_token, user_token)}
      else
        {nil, conn}
      end
    end
  end

  @doc """
  Used for routes that require the user to not be authenticated.
  """
  def redirect_if_user_is_authenticated(conn, _opts) do
    if conn.assigns[:current_user] do
      conn
      |> redirect(to: signed_in_path(conn))
      |> halt()
    else
      conn
    end
  end

  @doc """
  Used for routes that require the user to be authenticated.

  If you want to enforce the user email is confirmed before
  they use the application at all, here would be a good place.
  """
  def require_authenticated_user(conn, _opts) do
    if conn.assigns[:current_user] do
      conn
    else
      conn
      |> put_flash(:error, "You must log in to access this page.")
      |> maybe_store_return_to()
      |> redirect(to: Routes.user_session_path(conn, :new))
      |> halt()
    end
  end
  ---

それでは新たに、hello.html.heex を作成し、router.ex のそれぞれの箇所に組み込み、効果をみていきます。

lib/auth_test_web/templates/page/hello.html.heex
<h1>Hello World !!!</h1>
<%= if @current_user do %>
  <h2><%= @current_user.email %></h2>
<% else %>
  <h2>Guest</h2>
<% end %>

以下の実験を行う前に、ユーザ登録を行っておきます。

2-1. pipe_through :browser

router.ex に "/hello" パスを挿入します。

lib/auth_test_web/router.ex
  scope "/", AuthTestWeb do
    pipe_through :browser
    ---
    get "/hello", PageController, :hello  # ここに挿入
  end

未ログイン の状態で http://localhost:4000/hello にアクセスする。Guestが表示されました。

image.png

ログイン済 の状態で http://localhost:4000/hello にアクセスする。メールアドレスが表示されました。

image.png

2-2. pipe_through [:browser, :redirect_if_user_is_authenticated]

router.ex に "/hello" パスを挿入します。

lib/auth_test_web/router.ex
  scope "/", AuthTestWeb do
    pipe_through [:browser, :redirect_if_user_is_authenticated]
    ---
    get "/hello", PageController, :hello  # ここに挿入
  end

未ログイン の状態で http://localhost:4000/hello にアクセスする。Guestが表示されました。

image.png

ログイン済 の状態で http://localhost:4000/hello にアクセスする。トップページに リダイレクト されました。

image.png

2-3. pipe_through [:browser, :require_authenticated_user]

router.ex に "/hello" パスを挿入します。

lib/auth_test_web/router.ex
  scope "/", AuthTestWeb do
    pipe_through [:browser, :require_authenticated_user]
    ---
    get "/hello", PageController, :hello  # ここに挿入
  end

未ログイン の状態で http://localhost:4000/hello にアクセスする。ログイン画面にリダイレクトされました。

image.png

ログイン済 の状態で http://localhost:4000/hello にアクセスする。メールアドレスが表示されました。

image.png

今回は以上です。

Phoenixの良いところは、生成された template などはカスタマイズして使うことが前提となっているので、字面の日本語化やカスタマイズなどは簡単に行えることかなと感じてます。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?