Packages
samly
0.9.0
1.4.0
1.3.0
1.2.0
1.1.0
1.0.0
1.0.0-rc.1
retired
1.0.0-rc.0
retired
0.10.1
retired
0.10.0
retired
0.9.3
retired
0.9.2
retired
0.9.1
retired
0.9.0
retired
0.8.4
retired
0.8.3
retired
0.8.2
retired
0.8.1
retired
0.8.0
retired
0.7.2
retired
0.7.1
retired
0.7.0
retired
0.6.3
retired
0.6.2
retired
0.6.1
retired
0.6.0
retired
0.5.0
retired
0.4.0
retired
0.1.2
retired
SAML Single-Sign-On Authentication for Plug/Phoenix Applications
Retired package: Use versions >= 1.0.0
Current section
Files
Jump to
Current section
Files
lib/samly/router_util.ex
defmodule Samly.RouterUtil do
@moduledoc false
alias Plug.Conn
require Samly.Esaml
alias Samly.{Esaml, IdpData, Helper}
@subdomain_re ~r/^(?<subdomain>([^.]+))?\./
def check_idp_id(conn, _opts) do
idp_id_from = Application.get_env(:samly, :idp_id_from)
idp_id =
if idp_id_from == :subdomain do
case Regex.named_captures(@subdomain_re, conn.host) do
%{"subdomain" => idp_id} -> idp_id
_ -> nil
end
else
case conn.params["idp_id_seg"] do
[idp_id] -> idp_id
_ -> nil
end
end
idp = idp_id && Helper.get_idp(idp_id)
if idp do
conn |> Conn.put_private(:samly_idp, idp)
else
conn |> Conn.send_resp(403, "invalid_request unknown IdP") |> Conn.halt()
end
end
# generate URIs using the idp_id
@spec ensure_sp_uris_set(tuple, Conn.t()) :: tuple
def ensure_sp_uris_set(sp, conn) do
case Esaml.esaml_sp(sp, :metadata_uri) do
[?/ | _] ->
uri = %URI{
scheme: Atom.to_string(conn.scheme),
host: conn.host,
port: conn.port,
path: "/sso"
}
base_url = URI.to_string(uri)
idp_id_from = Application.get_env(:samly, :idp_id_from)
path_segment_idp_id =
if idp_id_from == :subdomain do
nil
else
%IdpData{id: idp_id} = conn.private[:samly_idp]
idp_id
end
Esaml.esaml_sp(
sp,
metadata_uri: Helper.get_metadata_uri(base_url, path_segment_idp_id),
consume_uri: Helper.get_consume_uri(base_url, path_segment_idp_id),
logout_uri: Helper.get_logout_uri(base_url, path_segment_idp_id)
)
_ ->
sp
end
end
def send_saml_request(conn, idp_url, use_redirect?, signed_xml_payload, relay_state) do
if use_redirect? do
url =
:esaml_binding.encode_http_redirect(idp_url, signed_xml_payload, :undefined, relay_state)
conn |> redirect(302, url)
else
resp_body = :esaml_binding.encode_http_post(idp_url, signed_xml_payload, relay_state)
conn
|> Conn.put_resp_header("Content-Type", "text/html")
|> Conn.send_resp(200, resp_body)
end
end
def redirect(conn, status_code, dest) do
conn
|> Conn.put_resp_header("Location", dest)
|> Conn.send_resp(status_code, "")
|> Conn.halt()
end
end