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.