Packages
samly
1.0.0-rc.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/helper.ex
defmodule Samly.Helper do
@moduledoc false
require Samly.Esaml
alias Samly.{Assertion, Esaml, IdpData}
@spec get_idp(binary) :: nil | IdpData.t()
def get_idp(idp_id) do
idps = Application.get_env(:samly, :identity_providers, %{})
Map.get(idps, idp_id)
end
@spec get_metadata_uri(nil | binary, binary) :: nil | charlist
def get_metadata_uri(nil, _idp_id), do: nil
def get_metadata_uri(sp_base_url, nil) when is_binary(sp_base_url) do
"#{sp_base_url}/sp/metadata" |> String.to_charlist()
end
def get_metadata_uri(sp_base_url, idp_id) when is_binary(sp_base_url) do
"#{sp_base_url}/sp/metadata/#{idp_id}" |> String.to_charlist()
end
@spec get_consume_uri(nil | binary, binary) :: nil | charlist
def get_consume_uri(nil, _idp_id), do: nil
def get_consume_uri(sp_base_url, nil) when is_binary(sp_base_url) do
"#{sp_base_url}/sp/consume" |> String.to_charlist()
end
def get_consume_uri(sp_base_url, idp_id) when is_binary(sp_base_url) do
"#{sp_base_url}/sp/consume/#{idp_id}" |> String.to_charlist()
end
@spec get_logout_uri(nil | binary, binary) :: nil | charlist
def get_logout_uri(nil, _idp_id), do: nil
def get_logout_uri(sp_base_url, nil) when is_binary(sp_base_url) do
"#{sp_base_url}/sp/logout" |> String.to_charlist()
end
def get_logout_uri(sp_base_url, idp_id) when is_binary(sp_base_url) do
"#{sp_base_url}/sp/logout/#{idp_id}" |> String.to_charlist()
end
def sp_metadata(sp) do
:xmerl.export([:esaml_sp.generate_metadata(sp)], :xmerl_xml)
end
def gen_idp_signin_req(sp, idp_metadata, nameid_format) do
idp_signin_url = Esaml.esaml_idp_metadata(idp_metadata, :login_location)
xml_frag = :esaml_sp.generate_authn_request(idp_signin_url, sp, nameid_format)
{idp_signin_url, xml_frag}
end
def gen_idp_signout_req(sp, idp_metadata, subject_rec, session_index) do
idp_signout_url = Esaml.esaml_idp_metadata(idp_metadata, :logout_location)
xml_frag = :esaml_sp.generate_logout_request(idp_signout_url, session_index, subject_rec, sp)
{idp_signout_url, xml_frag}
end
def gen_idp_signout_resp(sp, idp_metadata, signout_status) do
idp_signout_url = Esaml.esaml_idp_metadata(idp_metadata, :logout_location)
xml_frag = :esaml_sp.generate_logout_response(idp_signout_url, signout_status, sp)
{idp_signout_url, xml_frag}
end
def decode_idp_auth_resp(sp, saml_encoding, saml_response) do
with {:ok, xml_frag} <- decode_saml_payload(saml_encoding, saml_response),
{:ok, assertion_rec} <- :esaml_sp.validate_assertion(xml_frag, sp) do
{:ok, Assertion.from_rec(assertion_rec)}
else
error -> {:error, {:invalid_request, "#{inspect(error)}"}}
end
end
def decode_idp_signout_resp(sp, saml_encoding, saml_response) do
resp_ns = [
{'samlp', 'urn:oasis:names:tc:SAML:2.0:protocol'},
{'saml', 'urn:oasis:names:tc:SAML:2.0:assertion'},
{'ds', 'http://www.w3.org/2000/09/xmldsig#'}
]
with {:ok, xml_frag} <- decode_saml_payload(saml_encoding, saml_response),
nodes when is_list(nodes) and length(nodes) == 1 <-
:xmerl_xpath.string('/samlp:LogoutResponse', xml_frag, [{:namespace, resp_ns}]) do
:esaml_sp.validate_logout_response(xml_frag, sp)
else
_ -> {:error, :invalid_request}
end
end
def decode_idp_signout_req(sp, saml_encoding, saml_request) do
req_ns = [
{'samlp', 'urn:oasis:names:tc:SAML:2.0:protocol'},
{'saml', 'urn:oasis:names:tc:SAML:2.0:assertion'}
]
with {:ok, xml_frag} <- decode_saml_payload(saml_encoding, saml_request),
nodes when is_list(nodes) and length(nodes) == 1 <-
:xmerl_xpath.string('/samlp:LogoutRequest', xml_frag, [{:namespace, req_ns}]) do
:esaml_sp.validate_logout_request(xml_frag, sp)
else
_ -> {:error, :invalid_request}
end
end
defp decode_saml_payload(saml_encoding, saml_payload) do
try do
xml = :esaml_binding.decode_response(saml_encoding, saml_payload)
{:ok, xml}
rescue
error -> {:error, {:invalid_response, "#{inspect(error)}"}}
end
end
end