Skip to content

Instantly share code, notes, and snippets.

@dmitriid
Created June 2, 2023 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmitriid/2ae3ae7737c640e9a5de42e79bef1bfb to your computer and use it in GitHub Desktop.
Save dmitriid/2ae3ae7737c640e9a5de42e79bef1bfb to your computer and use it in GitHub Desktop.
Ash Auth0
## This porvides your settings and Auth0 secrets
## It should read them from env, but I have them hardcoded in dev :D
defmodule Telepai.Secrets do
use AshAuthentication.Secret
def secret_for([:authentication, :strategies, :auth0, :client_id], Telepai.Users.User, _) do
{:ok, "2D...."} #get_config(:client_id)
end
def secret_for([:authentication, :strategies, :auth0, :redirect_uri], Telepai.Users.User, _) do
{:ok, "http://localhost:4000/auth"} #get_config(:redirect_uri)
end
def secret_for([:authentication, :strategies, :auth0, :client_secret], Telepai.Users.User, _) do
{:ok, "Wmc-..."} #get_config(:client_secret)
end
def secret_for([:authentication, :strategies, :auth0, :site], Telepai.Users.User, _) do
{:ok, "https://<your-auth0-domain>.auth0.com"} #get_config(:site)
end
defp get_config(key) do
:my_app
|> Application.get_env(:auth0, [])
|> Keyword.fetch(key)
end
end
# Resource
defmodule Telepai.Users.User do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication]
postgres do
table("users")
repo(Telepai.Repo)
end
attributes do
uuid_primary_key(:id)
attribute(:email, :ci_string, allow_nil?: false)
attribute :name, :string do
allow_nil?(true)
constraints(trim?: true, allow_empty?: false)
end
attribute :nickname, :string do
allow_nil?(true)
constraints(trim?: true, allow_empty?: false)
end
attribute :picture, :string do
allow_nil?(true)
constraints(trim?: true, allow_empty?: false)
end
update_timestamp :updated_at
end
identities do
identity(:unique_email, [:email])
end
authentication do
api(Telepai.Users)
strategies do
auth0 do
client_id(Telepai.Secrets)
redirect_uri(Telepai.Secrets)
client_secret(Telepai.Secrets)
site(Telepai.Secrets)
end
end
end
actions do
defaults([:read])
create :register_with_auth0 do
argument(:user_info, :map, allow_nil?: false)
argument(:oauth_tokens, :map, allow_nil?: false)
upsert?(true)
upsert_identity(:unique_email)
change(fn changeset, _ ->
user_info = Ash.Changeset.get_argument(changeset, :user_info)
changeset
|> Ash.Changeset.change_attributes(
Map.take(user_info, ["email", "name", "nickname", "picture"])
)
end)
end
end
end
defmodule TelepaiWeb.AuthController do
use TelepaiWeb, :controller
use AshAuthentication.Phoenix.Controller
def success(conn, _activity, user, _token) do
return_to = get_session(conn, :return_to) || ~p"/"
conn
|> delete_session(:return_to)
|> store_in_session(user)
|> assign(:current_user, user)
|> redirect(to: return_to)
end
def failure(conn, _activity, _reason) do
conn
|> put_status(401)
|> render("failure.html")
end
def sign_out(conn, _params) do
return_to = get_session(conn, :return_to) || ~p"/"
conn
|> clear_session()
|> redirect(to: return_to)
end
end
defmodule TelepaiWeb.Router do
use TelepaiWeb, :router
use AshAuthentication.Phoenix.Router
...
scope "/", TelepaiWeb do
pipe_through :browser
# this comes from the next step:
# https://ash-hq.org/docs/guides/ash_phoenix/latest/tutorials/getting-started-with-ash-and-phoenix#connecting-your-resource-to-a-phoenix-liveview
ash_authentication_live_session :authentication_required,
on_mount: [
{TelepaiWeb.Hooks.LiveUserAuth, :live_user_required},
] do
live "/profile", Live.Profile
live "/", Live.Chat
end
# Ash auth
sign_in_route()
sign_out_route AuthController # See TelepaiWeb.AuthController below
auth_routes_for Telepai.Users.User, to: AuthController
reset_route []
# End Ash auth
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment