IntegrateBackends
Phoenix (Elixir) integration
Authenticate Phoenix routes against Olympus
Phoenix integrates with Olympus via standard OIDC. Use Ueberauth with the OIDC strategy.
Setup
mix.exs:
defp deps do
[
{:ueberauth, "~> 0.10"},
{:ueberauth_oidcc, "~> 0.3"}
]
endConfig
config/config.exs:
config :ueberauth, Ueberauth,
providers: [
olympus: {Ueberauth.Strategy.Oidcc, [
issuer: System.get_env("OLYMPUS_ISSUER"),
scopes: ["openid", "profile", "email"]
]}
]
config :ueberauth, Ueberauth.Strategy.Oidcc.OAuth,
client_id: System.get_env("OLYMPUS_CLIENT_ID"),
client_secret: System.get_env("OLYMPUS_CLIENT_SECRET"),
redirect_uri: System.get_env("OLYMPUS_REDIRECT_URI")Router
defmodule YourAppWeb.Router do
use YourAppWeb, :router
pipeline :auth do
plug Ueberauth
end
scope "/auth", YourAppWeb do
pipe_through [:browser, :auth]
get "/:provider", AuthController, :request
get "/:provider/callback", AuthController, :callback
post "/logout", AuthController, :logout
end
endController
defmodule YourAppWeb.AuthController do
use YourAppWeb, :controller
plug Ueberauth
def callback(%{assigns: %{ueberauth_auth: auth}} = conn, _params) do
user = %{
sub: auth.uid,
email: auth.info.email,
name: auth.info.name
}
conn
|> put_session(:current_user, user)
|> redirect(to: "/")
end
def logout(conn, _params) do
conn
|> clear_session()
|> redirect(external: "https://ciam.your-domain/oauth2/sessions/logout")
end
endAPI token validation
For API endpoints:
defmodule YourAppWeb.TokenAuth do
import Plug.Conn
def init(opts), do: opts
def call(conn, _opts) do
with ["Bearer " <> token] <- get_req_header(conn, "authorization"),
{:ok, info} <- introspect(token),
true <- info["active"] do
assign(conn, :user_sub, info["sub"])
else
_ -> conn |> send_resp(401, ~s({"error":"unauth"})) |> halt()
end
end
defp introspect(token) do
HTTPoison.post(
"#{System.get_env("OLYMPUS_ISSUER")}/admin/oauth2/introspect",
"token=#{token}",
[{"content-type", "application/x-www-form-urlencoded"}],
hackney: [basic_auth: {System.get_env("HYDRA_ADMIN_USER"), System.get_env("HYDRA_ADMIN_PASS")}]
)
|> case do
{:ok, %{body: body}} -> Jason.decode(body)
_ -> {:error, :introspection_failed}
end
end
endPhoenix LiveView
For LiveView pages, lift the session into the socket:
def on_mount(:default, _params, session, socket) do
user = session["current_user"]
if user, do: {:cont, assign(socket, :current_user, user)}, else: {:halt, redirect(socket, to: "/auth/olympus")}
endRelated
- Integrate, OAuth2 PKCE
- Cookbook, Validate access token (Node), same pattern in JS.