Skip to content

Commit 30db459

Browse files
committed
Add on error pipeline
1 parent 6115040 commit 30db459

3 files changed

Lines changed: 59 additions & 10 deletions

File tree

lib/samly/idp_data.ex

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ defmodule Samly.IdpData do
1616
custom_recipient_url: nil,
1717
metadata_file: nil,
1818
metadata: nil,
19+
on_error_pipeline: nil,
1920
pre_session_create_pipeline: nil,
2021
use_redirect_for_req: false,
2122
sign_requests: true,
@@ -45,6 +46,7 @@ defmodule Samly.IdpData do
4546
custom_recipient_url: nil | binary(),
4647
metadata_file: nil | binary(),
4748
metadata: nil | binary(),
49+
on_error_pipeline: nil | module(),
4850
pre_session_create_pipeline: nil | module(),
4951
use_redirect_for_req: boolean(),
5052
sign_requests: boolean(),
@@ -117,6 +119,7 @@ defmodule Samly.IdpData do
117119
%IdpData{idp_data | id: id, sp_id: sp_id, base_url: Map.get(opts_map, :base_url)}
118120
|> set_metadata(opts_map)
119121
|> set_pipeline(opts_map)
122+
|> set_error_pipeline(opts_map)
120123
|> set_custom_recipient_url(opts_map)
121124
|> set_allowed_target_urls(opts_map)
122125
|> set_boolean_attr(opts_map, :use_redirect_for_req)
@@ -206,6 +209,12 @@ defmodule Samly.IdpData do
206209
%IdpData{idp_data | pre_session_create_pipeline: pipeline}
207210
end
208211

212+
@spec set_error_pipeline(%IdpData{}, map()) :: %IdpData{}
213+
defp set_error_pipeline(%IdpData{} = idp_data, %{} = opts_map) do
214+
pipeline = Map.get(opts_map, :on_error_pipeline)
215+
%IdpData{idp_data | on_error_pipeline: pipeline}
216+
end
217+
209218
@spec set_custom_recipient_url(%IdpData{}, map()) :: %IdpData{}
210219
defp set_custom_recipient_url(%IdpData{} = idp_data, %{} = opts_map) do
211220
consume_url =
@@ -372,7 +381,9 @@ defmodule Samly.IdpData do
372381
idp_signs_assertions: idp_data.signed_assertion_in_resp,
373382
trusted_fingerprints: idp_data.fingerprints,
374383
metadata_uri: Helper.get_metadata_uri(idp_data.base_url, path_segment_idp_id),
375-
consume_uri: idp_data.custom_recipient_url || Helper.get_consume_uri(idp_data.base_url, path_segment_idp_id),
384+
consume_uri:
385+
idp_data.custom_recipient_url ||
386+
Helper.get_consume_uri(idp_data.base_url, path_segment_idp_id),
376387
logout_uri: Helper.get_logout_uri(idp_data.base_url, path_segment_idp_id),
377388
entity_id: sp_entity_id
378389
)

lib/samly/sp_handler.ex

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ defmodule Samly.SPHandler do
2727

2828
def consume_signin_response(conn) do
2929
%IdpData{id: idp_id} = idp = conn.private[:samly_idp]
30-
%IdpData{pre_session_create_pipeline: pipeline, esaml_sp_rec: sp_rec} = idp
30+
31+
%IdpData{
32+
pre_session_create_pipeline: pipeline,
33+
on_error_pipeline: error_pipeline,
34+
esaml_sp_rec: sp_rec
35+
} = idp
36+
3137
sp = ensure_sp_uris_set(sp_rec, conn)
3238

3339
saml_encoding = conn.body_params["SAMLEncoding"]
@@ -53,17 +59,42 @@ defmodule Samly.SPHandler do
5359
|> put_session_new("samly_assertion_key", assertion_key)
5460
|> redirect(302, target_url)
5561
else
56-
{:halted, conn} -> conn
62+
{:halted, conn} ->
63+
conn
64+
5765
{:error, reason} ->
58-
case idp do
59-
%IdpData{debug_mode: true} ->
66+
{_, assertion_or_error} = Helper.decode_idp_auth_resp(sp, saml_encoding, saml_response)
67+
68+
conn
69+
|> put_private(:samly_error, reason)
70+
|> put_private(:samly_assertion, assertion_or_error)
71+
|> then(fn conn ->
72+
if idp.debug_mode do
73+
put_private(conn, :samly_saml_response, saml_response)
74+
else
6075
conn
61-
|> put_resp_header("content-type", "text/html")
62-
|> send_resp(403, "<html><body><div><h1>access_denied</h1><p><b>Error:</b><br /><pre><code>#{inspect(reason)}</code></pre></p><p><b>Raw Response:</b><br /><pre><code>#{saml_response}</code></pre></p></div></body></html")
63-
_ ->
64-
conn |> send_resp(403, "access_denied #{inspect(reason)}")
76+
end
77+
end)
78+
|> pipethrough(error_pipeline)
79+
|> case do
80+
%Conn{halted: true} = conn ->
81+
{:halted, conn}
82+
83+
conn ->
84+
if idp.debug_mode do
85+
conn
86+
|> put_resp_header("content-type", "text/html")
87+
|> send_resp(
88+
403,
89+
"<html><body><div><h1>access_denied</h1><p><b>Error:</b><br /><pre><code>#{inspect(reason)}</code></pre></p><p><b>Raw Response:</b><br /><pre><code>#{saml_response}</code></pre></p></div></body></html"
90+
)
91+
else
92+
conn |> send_resp(403, "access_denied #{inspect(reason)}")
93+
end
6594
end
66-
_ -> conn |> send_resp(403, "access_denied")
95+
96+
_ ->
97+
conn |> send_resp(403, "access_denied")
6798
end
6899

69100
# rescue

test/samly_idp_data_test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ defmodule SamlyIdpDataTest do
177177
assert idp_data.custom_recipient_url == ~c"custom-recipient-url"
178178
end
179179

180+
test "valid-idp-config-13", %{sps: sps} do
181+
idp_config = Map.put(@idp_config1, :on_error_pipeline, MyErrorPipeline)
182+
%IdpData{} = idp_data = IdpData.load_provider(idp_config, sps)
183+
assert idp_data.valid?
184+
assert idp_data.on_error_pipeline == MyErrorPipeline
185+
end
186+
180187
test "url-test-1", %{sps: sps} do
181188
idp_config = %{@idp_config1 | metadata_file: "test/data/shibboleth_idp_metadata.xml"}
182189
%IdpData{} = idp_data = IdpData.load_provider(idp_config, sps)

0 commit comments

Comments
 (0)