From 70ed068debe7a711ba36e2eb4fcf60be8cae4681 Mon Sep 17 00:00:00 2001 From: Arne Date: Thu, 1 Dec 2022 11:56:52 +0100 Subject: [PATCH] feat: forward parsed request cookies to webhook Jsonnet snippet (#2917) Request cookies were already available in raw form in the ctx.request_headers top-level argument to the Jsonnet snippet. Parsing cookies in Jsonnet is tedious and error-prone, though, so we parse them internally for convenience. --- selfservice/hook/stub/test_body.jsonnet | 3 +- selfservice/hook/web_hook.go | 23 ++++++++++ selfservice/hook/web_hook_integration_test.go | 43 ++++++++++++++++--- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/selfservice/hook/stub/test_body.jsonnet b/selfservice/hook/stub/test_body.jsonnet index 7df9528a83e0..0b2639368474 100644 --- a/selfservice/hook/stub/test_body.jsonnet +++ b/selfservice/hook/stub/test_body.jsonnet @@ -3,5 +3,6 @@ function(ctx) { identity_id: if std.objectHas(ctx, "identity") then ctx.identity.id, headers: ctx.request_headers, url: ctx.request_url, - method: ctx.request_method + method: ctx.request_method, + cookies: ctx.request_cookies, } diff --git a/selfservice/hook/web_hook.go b/selfservice/hook/web_hook.go index 70a17c99a25c..98bc24fc27c3 100644 --- a/selfservice/hook/web_hook.go +++ b/selfservice/hook/web_hook.go @@ -57,6 +57,7 @@ type ( RequestHeaders http.Header `json:"request_headers"` RequestMethod string `json:"request_method"` RequestURL string `json:"request_url"` + RequestCookies map[string]string `json:"request_cookies"` Identity *identity.Identity `json:"identity,omitempty"` } @@ -82,6 +83,16 @@ type ( } ) +func cookies(req *http.Request) map[string]string { + cookies := make(map[string]string) + for _, c := range req.Cookies() { + if c.Name != "" { + cookies[c.Name] = c.Value + } + } + return cookies +} + func NewWebHook(r webHookDependencies, c json.RawMessage) *WebHook { return &WebHook{deps: r, conf: c} } @@ -93,6 +104,7 @@ func (e *WebHook) ExecuteLoginPreHook(_ http.ResponseWriter, req *http.Request, RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), }) } @@ -103,6 +115,7 @@ func (e *WebHook) ExecuteLoginPostHook(_ http.ResponseWriter, req *http.Request, RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), Identity: session.Identity, }) } @@ -114,6 +127,7 @@ func (e *WebHook) ExecuteVerificationPreHook(_ http.ResponseWriter, req *http.Re RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), }) } @@ -124,6 +138,7 @@ func (e *WebHook) ExecutePostVerificationHook(_ http.ResponseWriter, req *http.R RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), Identity: id, }) } @@ -134,6 +149,7 @@ func (e *WebHook) ExecuteRecoveryPreHook(_ http.ResponseWriter, req *http.Reques Flow: flow, RequestHeaders: req.Header, RequestMethod: req.Method, + RequestCookies: cookies(req), RequestURL: x.RequestURL(req).String(), }) } @@ -145,6 +161,7 @@ func (e *WebHook) ExecutePostRecoveryHook(_ http.ResponseWriter, req *http.Reque RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), Identity: session.Identity, }) } @@ -156,6 +173,7 @@ func (e *WebHook) ExecuteRegistrationPreHook(_ http.ResponseWriter, req *http.Re RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), }) } @@ -170,6 +188,7 @@ func (e *WebHook) ExecutePostRegistrationPrePersistHook(_ http.ResponseWriter, r RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), Identity: id, }) } @@ -185,6 +204,7 @@ func (e *WebHook) ExecutePostRegistrationPostPersistHook(_ http.ResponseWriter, RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), Identity: session.Identity, }) } @@ -196,6 +216,7 @@ func (e *WebHook) ExecuteSettingsPreHook(_ http.ResponseWriter, req *http.Reques RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), }) } @@ -210,6 +231,7 @@ func (e *WebHook) ExecuteSettingsPostPersistHook(_ http.ResponseWriter, req *htt RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), Identity: id, }) } @@ -225,6 +247,7 @@ func (e *WebHook) ExecuteSettingsPrePersistHook(_ http.ResponseWriter, req *http RequestHeaders: req.Header, RequestMethod: req.Method, RequestURL: x.RequestURL(req).String(), + RequestCookies: cookies(req), Identity: id, }) } diff --git a/selfservice/hook/web_hook_integration_test.go b/selfservice/hook/web_hook_integration_test.go index 03a3f6d09bd7..091e73d24625 100644 --- a/selfservice/hook/web_hook_integration_test.go +++ b/selfservice/hook/web_hook_integration_test.go @@ -119,7 +119,12 @@ func TestWebHooks(t *testing.T) { "identity_id": null, "headers": %s, "method": "%s", - "url": "%s" + "url": "%s", + "cookies": { + "Some-Cookie-1": "Some-Cookie-Value", + "Some-Cookie-2": "Some-other-Cookie-Value", + "Some-Cookie-3": "Third-Cookie-Value" + } }`, f.GetID(), string(h), req.Method, "http://www.ory.sh/some_end_point") } @@ -130,7 +135,12 @@ func TestWebHooks(t *testing.T) { "identity_id": "%s", "headers": %s, "method": "%s", - "url": "%s" + "url": "%s", + "cookies": { + "Some-Cookie-1": "Some-Cookie-Value", + "Some-Cookie-2": "Some-other-Cookie-Value", + "Some-Cookie-3": "Third-Cookie-Value" + } }`, f.GetID(), s.Identity.ID, string(h), req.Method, "http://www.ory.sh/some_end_point") } @@ -275,12 +285,28 @@ func TestWebHooks(t *testing.T) { t.Run("method="+method, func(t *testing.T) { f := tc.createFlow() req := &http.Request{ - Host: "www.ory.sh", - Header: map[string][]string{"Some-Header": {"Some-Value"}}, + Host: "www.ory.sh", + Header: map[string][]string{ + "Some-Header": {"Some-Value"}, + "Cookie": {"Some-Cookie-1=Some-Cookie-Value; Some-Cookie-2=Some-other-Cookie-Value", "Some-Cookie-3=Third-Cookie-Value"}, + }, RequestURI: "/some_end_point", Method: http.MethodPost, URL: &url.URL{Path: "/some_end_point"}, } + cookie, err := req.Cookie("Some-Cookie-1") + require.NoError(t, err) + require.Equal(t, cookie.Name, "Some-Cookie-1") + require.Equal(t, cookie.Value, "Some-Cookie-Value") + cookie, err = req.Cookie("Some-Cookie-2") + require.NoError(t, err) + require.Equal(t, cookie.Name, "Some-Cookie-2") + require.Equal(t, cookie.Value, "Some-other-Cookie-Value") + cookie, err = req.Cookie("Some-Cookie-3") + require.NoError(t, err) + require.Equal(t, cookie.Name, "Some-Cookie-3") + require.Equal(t, cookie.Value, "Third-Cookie-Value") + s := &session.Session{ID: x.NewUUID(), Identity: &identity.Identity{ID: x.NewUUID()}} whr := &WebHookRequest{} ts := newServer(webHookEndPoint(whr)) @@ -293,7 +319,7 @@ func TestWebHooks(t *testing.T) { wh := hook.NewWebHook(&whDeps, conf) - err := tc.callWebHook(wh, req, f, s) + err = tc.callWebHook(wh, req, f, s) if method == "GARBAGE" { assert.Error(t, err) return @@ -541,8 +567,11 @@ func TestWebHooks(t *testing.T) { t.Run("method="+method, func(t *testing.T) { f := tc.createFlow() req := &http.Request{ - Host: "www.ory.sh", - Header: map[string][]string{"Some-Header": {"Some-Value"}, "X-Forwarded-Proto": {"https"}}, + Host: "www.ory.sh", + Header: map[string][]string{ + "Some-Header": {"Some-Value"}, + "X-Forwarded-Proto": {"https"}, + "Cookie": {"Some-Cookie-1=Some-Cookie-Value; Some-Cookie-2=Some-other-Cookie-Value", "Some-Cookie-3=Third-Cookie-Value"}}, RequestURI: "/some_end_point", Method: http.MethodPost, URL: &url.URL{