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

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
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
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews