Switch to upstream version of `simple_saml` (#5554)

* Switch to upstream `simple_saml` and bump deps to avoid conflicts

* Simplify SAML attribute extraction
This commit is contained in:
Adrian Gruntkowski 2025-07-07 11:37:25 +02:00 committed by GitHub
parent 3c6db4efeb
commit 20657d4eab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 44 deletions

View File

@ -3,7 +3,6 @@ defmodule PlausibleWeb.SSO.RealSAMLAdapter do
Real implementation of SAML authentication interface.
"""
alias Plausible.Auth.SSO
alias SimpleXml.XmlNode
alias PlausibleWeb.Router.Helpers, as: Routes
@ -86,7 +85,7 @@ defmodule PlausibleWeb.SSO.RealSAMLAdapter do
public_key = X509.Certificate.public_key(cert),
:ok <-
SimpleSaml.verify_and_validate_response(root, assertion, public_key, @verify_opts),
{:ok, attributes} <- extract_attributes(root) do
{:ok, attributes} <- extract_attributes(assertion) do
session_timeout_minutes = integration.team.policy.sso_session_timeout_minutes
expires_at =
@ -128,49 +127,33 @@ defmodule PlausibleWeb.SSO.RealSAMLAdapter do
|> String.trim()
end
defp extract_attributes(root_node) do
with {:ok, assertion_node} <- XmlNode.first_child(root_node, ~r/.*:?Assertion$/),
{:ok, attributes_node} <-
XmlNode.first_child(assertion_node, ~r/.*:?AttributeStatement$/),
{:ok, attribute_nodes} <- XmlNode.children(attributes_node) do
found = get_attributes(attribute_nodes)
defp extract_attributes(assertion) do
attributes =
Enum.reduce([:email, :first_name, :last_name], %{}, fn field, attrs ->
value =
assertion.attributes
|> Map.get(to_string(field), [])
|> List.first()
attributes = %{
email: String.trim(found["email"] || ""),
first_name: String.trim(found["first_name"] || ""),
last_name: String.trim(found["last_name"] || "")
}
Map.put(attrs, field, String.trim(value || ""))
end)
cond do
attributes.email == "" ->
{:error, :missing_email_attribute}
cond do
attributes.email == "" ->
{:error, :missing_email_attribute}
# very rudimentary way to check if the attribute is at least email-like
not String.contains?(attributes.email, "@") or String.length(attributes.email) < 3 ->
{:error, :invalid_email_attribute}
# very rudimentary way to check if the attribute is at least email-like
not String.contains?(attributes.email, "@") or String.length(attributes.email) < 3 ->
{:error, :invalid_email_attribute}
attributes.first_name == "" and attributes.last_name == "" ->
{:error, :missing_name_attributes}
attributes.first_name == "" and attributes.last_name == "" ->
{:error, :missing_name_attributes}
true ->
{:ok, attributes}
end
true ->
{:ok, attributes}
end
end
defp get_attributes(nodes) do
Enum.reduce(nodes, %{}, fn node, attributes ->
with {:ok, name} <- XmlNode.attribute(node, "Name"),
{:ok, value_node} <- XmlNode.first_child(node, ~r/.*:?AttributeValue$/),
{:ok, value} <- XmlNode.text(value_node) do
Map.put(attributes, name, value)
else
_ ->
attributes
end
end)
end
defp safe_decode_www_form(nil), do: ""
defp safe_decode_www_form(data), do: URI.decode_www_form(data)

View File

@ -114,7 +114,6 @@ defmodule Plausible.MixProject do
{:plug, "~> 1.13", override: true},
{:plug_cowboy, "~> 2.3"},
{:polymorphic_embed, "~> 5.0"},
{:x509, "~> 0.8.10"},
{:postgrex, "~> 0.19.0"},
{:prom_ex, "~> 1.8"},
{:peep, "~> 3.4"},
@ -122,7 +121,7 @@ defmodule Plausible.MixProject do
{:ref_inspector, "~> 2.0"},
{:referrer_blocklist, git: "https://github.com/plausible/referrer-blocklist.git"},
{:sentry, "~> 10.8.1"},
{:simple_saml, git: "https://github.com/MBXSystems/simple_saml.git", branch: "main"},
{:simple_saml, "~> 1.2"},
{:xml_builder, "~> 2.1"},
{:siphash, "~> 3.2"},
{:timex, "~> 3.7"},

View File

@ -139,14 +139,14 @@
"referrer_blocklist": {:git, "https://github.com/plausible/referrer-blocklist.git", "d6f52c225cccb4f04b80e3a5d588868ec234139d", []},
"req": {:hex, :req, "0.5.6", "8fe1eead4a085510fe3d51ad854ca8f20a622aae46e97b302f499dfb84f726ac", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cfaa8e720945d46654853de39d368f40362c2641c4b2153c886418914b372185"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.7.3", "42cb9449785cd86c87453e39afdd27a0bdfa5c77a4ec5dc5ce45112e06b9f89b", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "cbc4b3777682e5f6f43ed39b0e0b4a42dccde8053aba91b4514e8f5ff9a5ac6d"},
"saxy": {:hex, :saxy, "1.5.0", "0141127f2d042856f135fb2d94e0beecda7a2306f47546dbc6411fc5b07e28bf", [:mix], [], "hexpm", "ea7bb6328fbd1f2aceffa3ec6090bfb18c85aadf0f8e5030905e84235861cf89"},
"saxy": {:hex, :saxy, "1.6.0", "02cb4e9bd045f25ac0c70fae8164754878327ee393c338a090288210b02317ee", [:mix], [], "hexpm", "ef42eb4ac983ca77d650fbdb68368b26570f6cc5895f0faa04d34a6f384abad3"},
"scrivener": {:hex, :scrivener, "2.7.2", "1d913c965ec352650a7f864ad7fd8d80462f76a32f33d57d1e48bc5e9d40aba2", [:mix], [], "hexpm", "7866a0ec4d40274efbee1db8bead13a995ea4926ecd8203345af8f90d2b620d9"},
"scrivener_ecto": {:hex, :scrivener_ecto, "2.7.0", "cf64b8cb8a96cd131cdbcecf64e7fd395e21aaa1cb0236c42a7c2e34b0dca580", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm", "e809f171687806b0031129034352f5ae44849720c48dd839200adeaf0ac3e260"},
"sentry": {:hex, :sentry, "10.8.1", "aa45309785e1521416225adb16e0b4d8b957578804527f3c7babb6fefbc5e456", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "495b3cdadad90ba72eef973aa3dec39b3b8b2a362fe87e2f4ef32133ac3b4097"},
"simple_saml": {:git, "https://github.com/MBXSystems/simple_saml.git", "d161dbc6cc059bddccdc986a0e1b29823e4348fd", [branch: "main"]},
"simple_xml": {:hex, :simple_xml, "1.3.1", "66813a84f650c4ac041ac9b0497d35448cadc5826a6d71a4dd2a33f015f48197", [:mix], [{:saxy, "~> 1.5", [hex: :saxy, repo: "hexpm", optional: false]}, {:x509, "~> 0.8.7", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "67dc14276a7f71bdb868f345e0d63e52db49da54521cb43eb2c7aac67ef7147d"},
"simple_saml": {:hex, :simple_saml, "1.2.0", "d875939e21cd73cdb3f747e701e4d2d5f0f4e35610d37df50629087454fa43f9", [:mix], [{:simple_xml, "~> 1.3", [hex: :simple_xml, repo: "hexpm", optional: false]}, {:x509, "~> 0.9.0", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "24663665e53a91bfc38359ed9f26f575a389bde9fc94ec369f9f2259046feaf0"},
"simple_xml": {:hex, :simple_xml, "1.3.2", "84b892527b5183748694583a658c729c84bb89fc8ac650d7025ebc2c49e74018", [:mix], [{:saxy, "~> 1.5", [hex: :saxy, repo: "hexpm", optional: false]}, {:x509, "~> 0.9.0", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "8c15fa49955a8c82b50f3053617e8a4cd771fcd0a502d660e56993c38ac86ca5"},
"siphash": {:hex, :siphash, "3.2.0", "ec03fd4066259218c85e2a4b8eec4bb9663bc02b127ea8a0836db376ba73f2ed", [:make, :mix], [], "hexpm", "ba3810701c6e95637a745e186e8a4899087c3b079ba88fb8f33df054c3b0b7c3"},
"site_encrypt": {:git, "https://github.com/sasa1977/site_encrypt.git", "046fbeca11b889604dafd2df6a71001f8abe5e2c", []},
"site_encrypt": {:git, "https://github.com/sasa1977/site_encrypt.git", "8d47801c51eeea11ac385cb73eef4ed9a6565367", []},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"},
"tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"},
@ -161,7 +161,7 @@
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
"x509": {:hex, :x509, "0.8.10", "5d1ec6d5f4db31982f9dc34e6a1eebd631d04599e0b6c1c259f1dadd4495e11f", [:mix], [], "hexpm", "a191221665af28b9bdfff0c986ef55f80e126d8ce751bbdf6cefa846410140c0"},
"x509": {:hex, :x509, "0.9.1", "c92026a17b7d93f19029842ca218f82ec1f1e7cc9d4aa0c48327ee778f7f482e", [:mix], [], "hexpm", "99328951a1480cfd7b1b8aa688f857f7f5bbea03077b78cad211fb3b30c2f4a8"},
"xml_builder": {:hex, :xml_builder, "2.4.0", "b20d23077266c81f593360dc037ea398461dddb6638a329743da6c73afa56725", [:mix], [], "hexpm", "833e325bb997f032b5a1b740d2fd6feed3c18ca74627f9f5f30513a9ae1a232d"},
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
"zstream": {:hex, :zstream, "0.6.5", "ad4c5631f0da986ddcf8b23d0d2c696c09cedb1c3ace027fb2312a809df6f8b8", [:mix], [], "hexpm", "de908d8a050f6aabf5f4931aa41dab49419e3c8b95cfee01461a8c84fdde005e"},