michael_teter

michael_teter

Can someone with current experience suggest a path on how to get started externalizing user authentication within Phoenix? I would like to give my users the ability to register/sign-in using Google, Facebook, etc.

Further, if I integrate with enough external providers, I assume that means I could (potentially?) forego entirely the responsibility of storing/managing users passwords. Is that a reasonable assumption?

There is a lot of information about this topic, but most of it seems dated… and the Elixir/Phoenix world moves quickly. I’d like to avoid starting on a dead-end path :).

Thanks in advance!

Showing Posts 1 to 5

kokolegorille

kokolegorille

Did You try ueberauth?

dustinfarris

dustinfarris

You might check out Auth0. I haven’t used it personally, but I’ve seen others use it with success especially when bootstrapping a project.

They also wrote a blog post on using it with Elixir (and uberauth):

danschultzer

danschultzer

Pow Core Team

Do you still want to register the users? I wrote CoherenceAssent to handle multi-provider login. While it’s built to use Coherence, I’ve been using it for just Github OAuth login in an admin interface where I just store the user information in the session. The controller looks like this:

defmodule MyAdminApp.AuthController do
  use MyAdminApp, :controller

  @organization "my-organization"

  @spec new(Conn.t, map) :: Conn.t
  def new(conn, _params) do
    config = Keyword.put(config(), :redirect_uri, callback_url(conn))
    {:ok, %{conn: conn, url: url}} = CoherenceAssent.Strategy.Github.authorize_url(conn, config)

    redirect(conn, external: url)
  end

  @spec callback(Conn.t, map) :: Conn.t
  def callback(conn, params) do
    params = Map.merge(%{"redirect_uri" => callback_url(conn)}, params)

    conn
    |> CoherenceAssent.Strategy.Github.callback(config(), params)
    |> verify_organization()
    |> login_or_redirect()
  end

  defp login_or_redirect({:ok, %{conn: conn, user: user}}) do
    conn
    |> put_session(:current_admin_user, user)
    |> redirect(to: index_path(conn, :index))
  end
  defp login_or_redirect({:error, %{error: error}}) do
    raise error
  end

  defp config do
    config = Application.get_env(:my_admin_app, :admin_github_provider) || raise "Need to set :admin_github_provider first!"
    Keyword.put(config, :authorization_params, [scope: "read:user,user:email,read:org"])
  end

  defp verify_organization({:error, error}), do: {:error, error}
  defp verify_organization({:ok, %{conn: conn, client: client, user: user}}) do
    case OAuth2.Client.get(client, "/user/orgs") do
      {:ok, %OAuth2.Response{body: orgs}} ->
        case Enum.find_value(orgs, &(&1["login"] == @organization)) do
          true -> {:ok, %{conn: conn, user: user}}
          _    -> {:error, %{error: "#{user["nickname"]} is not a member of #{@organization}"}}
        end

      {:error, error} ->
        {:error, %{conn: conn, error: error}}
    end
  end

  defp callback_url(conn) do
    auth_url(conn, :callback)
  end
end

And the plug looks like this:

defmodule MyAdminApp.Plug.RequireLogin do
  @moduledoc false

  import Plug.Conn
  import Phoenix.Controller, only: [redirect: 2]
  alias MyAdminApp.Router.Helpers

  @behaviour Plug

  @dialyzer [
    {:nowarn_function, call: 2},
    {:nowarn_function, init: 1},
  ]

  @spec init(Keyword.t) :: [tuple]
  def init(options) do
    %{option: options}
  end

  @spec call(Plug.Conn.t, any) :: Plug.Conn.t
  def call(conn, _opts) do
    user = get_session(conn, :current_admin_user)

    if user do
      conn
      |> assign(:current_admin_user, user)
    else
      conn
      |> redirect(to: Helpers.auth_path(conn, :new))
      |> halt
    end
  end

end

Routes:

# ...
  pipeline :protected do
    plug NomadRentalAdmin.Plug.RequireLogin
  end

  scope "/", MyAdminApp do
    pipe_through [:browser]

    get "/auth", AuthController, :new
    get "/auth/callback", AuthController, :callback
  end
# ...

It’s a very basic setup (since we’re just using it to log in to an internal admin interface with our Github organization), but might be something like this you’re looking for?

If you want to register the users still then I recommend checking out the readme for CoherenceAssent. It takes a minute, and then you can remove the ability to change the password on user admin page.

Kurisu

Kurisu

Great work!
That is what I’m looking for. I’m using Phauxth instead of Coherence but after what I saw on your own library Pow, I will definitely give it a try.

Thank you for sharing this. ^^

danschultzer

danschultzer

Pow Core Team

Thanks! I hope it works for you.

PowAssent has been improved to not be dependent on Plug, so if you use it without any user registration like in the example above, the API is a little different. But if you use Pow for user registration then there’s nothing you have to think about :smile:

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
psy-q
I’m trying to set up Emacs with elixir-ls via lsp-mode and credo via Flycheck. This should mostly be preconfigured as Flycheck picks up c...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews