|
9 | 9 | -module(sp_handler). |
10 | 10 | -include_lib("esaml/include/esaml.hrl"). |
11 | 11 |
|
12 | | --record(state, {sp, idp}). |
13 | | --export([init/3, handle/2, terminate/3]). |
| 12 | +-export([init/2, terminate/3]). |
14 | 13 |
|
15 | | -init(_Transport, Req, _Args) -> |
| 14 | +init(Req, State = #{initialized := true}) -> |
| 15 | + Operation = cowboy_req:binding(operation, Req), |
| 16 | + Method = cowboy_req:method(Req), |
| 17 | + io:format("[Method] ~p~n", [Method]), |
| 18 | + io:format("[Operation] ~p~n", [Operation]), |
| 19 | + io:format("[State] ~p~n", [State]), |
| 20 | + handle(Method, Operation, Req, State); |
| 21 | + |
| 22 | +init(Req, State) -> |
16 | 23 | % Load the certificate and private key for the SP |
17 | 24 | PrivKey = esaml_util:load_private_key("priv/test.key"), |
18 | 25 | Cert = esaml_util:load_certificate("priv/test.crt"), |
@@ -41,44 +48,40 @@ init(_Transport, Req, _Args) -> |
41 | 48 | % (this call will cache after the first time around, so it will be fast) |
42 | 49 | IdpMeta = esaml_util:load_metadata("https://some.idp.com/idp/saml2/idp/metadata.php"), |
43 | 50 |
|
44 | | - {ok, Req, #state{sp = SP, idp = IdpMeta}}. |
45 | | - |
46 | | -handle(Req, S = #state{}) -> |
47 | | - {Operation, Req2} = cowboy_req:binding(operation, Req), |
48 | | - {Method, Req3} = cowboy_req:method(Req2), |
49 | | - handle(Method, Operation, Req3, S). |
| 51 | + State1 = State#{sp => SP, idp => IdpMeta, initialized => true}, |
| 52 | + init(Req, State1). |
50 | 53 |
|
51 | 54 | % Return our SP metadata as signed XML |
52 | | -handle(<<"GET">>, <<"metadata">>, Req, S = #state{sp = SP}) -> |
53 | | - {ok, Req2} = esaml_cowboy:reply_with_metadata(SP, Req), |
54 | | - {ok, Req2, S}; |
| 55 | +handle(<<"GET">>, <<"metadata">>, Req, State = #{sp := SP}) -> |
| 56 | + Req2 = esaml_cowboy:reply_with_metadata(SP, Req), |
| 57 | + {ok, Req2, State}; |
55 | 58 |
|
56 | 59 | % Visit /saml/auth to start the authentication process -- we will make an AuthnRequest |
57 | 60 | % and send it to our IDP |
58 | | -handle(<<"GET">>, <<"auth">>, Req, S = #state{sp = SP, |
59 | | - idp = #esaml_idp_metadata{login_location = IDP}}) -> |
60 | | - {ok, Req2} = esaml_cowboy:reply_with_authnreq(SP, IDP, <<"foo">>, Req), |
61 | | - {ok, Req2, S}; |
| 61 | +handle(<<"GET">>, <<"auth">>, Req, State = #{sp := SP, |
| 62 | + idp := #esaml_idp_metadata{login_location = IDP}}) -> |
| 63 | + Req2 = esaml_cowboy:reply_with_authnreq(SP, IDP, <<"foo">>, Req), |
| 64 | + {ok, Req2, State}; |
62 | 65 |
|
63 | 66 | % Handles HTTP-POST bound assertions coming back from the IDP. |
64 | | -handle(<<"POST">>, <<"consume">>, Req, S = #state{sp = SP}) -> |
| 67 | +handle(<<"POST">>, <<"consume">>, Req, State = #{sp := SP}) -> |
65 | 68 | case esaml_cowboy:validate_assertion(SP, fun esaml_util:check_dupe_ets/2, Req) of |
66 | 69 | {ok, Assertion, RelayState, Req2} -> |
67 | 70 | Attrs = Assertion#esaml_assertion.attributes, |
68 | 71 | Uid = proplists:get_value(uid, Attrs), |
69 | 72 | Output = io_lib:format("<html><head><title>SAML SP demo</title></head><body><h1>Hi there!</h1><p>This is the <code>esaml_sp_default</code> demo SP callback module from eSAML.</p><table><tr><td>Your name:</td><td>\n~p\n</td></tr><tr><td>Your UID:</td><td>\n~p\n</td></tr></table><hr /><p>RelayState:</p><pre>\n~p\n</pre><p>The assertion I got was:</p><pre>\n~p\n</pre></body></html>", [Assertion#esaml_assertion.subject#esaml_subject.name, Uid, RelayState, Assertion]), |
70 | | - {ok, Req3} = cowboy_req:reply(200, [{<<"Content-Type">>, <<"text/html">>}], Output, Req2), |
71 | | - {ok, Req3, S}; |
| 73 | + Req3 = cowboy_req:reply(200, #{<<"Content-Type">> => <<"text/html">>}, Output, Req2), |
| 74 | + {ok, Req3, State}; |
72 | 75 |
|
73 | 76 | {error, Reason, Req2} -> |
74 | | - {ok, Req3} = cowboy_req:reply(403, [{<<"content-type">>, <<"text/plain">>}], |
| 77 | + Req3 = cowboy_req:reply(403, #{<<"content-type">> => <<"text/plain">>}, |
75 | 78 | ["Access denied, assertion failed validation:\n", io_lib:format("~p\n", [Reason])], |
76 | 79 | Req2), |
77 | | - {ok, Req3, S} |
| 80 | + {ok, Req3, State} |
78 | 81 | end; |
79 | 82 |
|
80 | | -handle(_, _, Req, S = #state{}) -> |
81 | | - {ok, Req2} = cowboy_req:reply(404, [], <<"Not found">>, Req), |
82 | | - {ok, Req2, S}. |
| 83 | +handle(_, _, Req, State = #{}) -> |
| 84 | + Req2 = cowboy_req:reply(404, #{}, <<"Not found">>, Req), |
| 85 | + {ok, Req2, State}. |
83 | 86 |
|
84 | 87 | terminate(_Reason, _Req, _State) -> ok. |
0 commit comments