The default Noizu.MCP.Auth.Server.Upstream: reuse the host application's
existing login.
The host already knows how to authenticate a person — session cookie, Authentik OIDC, MFA, the lot. Two callbacks are all this needs:
upstream: {Noizu.MCP.Auth.Server.Upstream.HostSession,
current_subject: {MyApp.Auth.MCPBridge, :current_subject},
login_url: {MyApp.Auth.MCPBridge, :login_url}}
defmodule MyApp.Auth.MCPBridge do
# (conn) -> {:ok, subject} | {:ok, %{subject: ...}} | :none
def current_subject(conn) do
case conn.assigns[:current_user] do
%{id: id} -> {:ok, to_string(id)}
_ -> :none
end
end
# (conn, return_to) -> url the browser should be sent to
def login_url(_conn, return_to),
do: "/sso/oidc?return_to=" <> URI.encode_www_form(return_to)
endreturn_to is the authorization endpoint with the login state attached, so the
user lands back mid-flow. Validate it same-origin in the host's SSO
controller: a return_to an attacker chose is an open redirect, and the login
screen is exactly where someone will try one. The URL this module builds is
always same-origin with the configured issuer, so a same-origin check never
rejects a legitimate one.
Options
:current_subject(required) —{mod, fun}or 1-arity fun over the conn:login_url(required) —{mod, fun}or 2-arity fun(conn, return_to):return_to— override how the return URL is built,(conn, state, config)
The upstream session is used to answer one question — who is this? — and nothing else. No upstream token is read, stored, or passed on.