Noizu.MCP.Auth.Server.Upstream.HostSession (Noizu MCP v0.1.6)

Copy Markdown View Source

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)
end

return_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.