From b0bb1aa8ea2c9497f6c1af820ec4fd0134d42f6d Mon Sep 17 00:00:00 2001 From: Trong Huu Nguyen Date: Wed, 3 May 2023 09:07:03 +0200 Subject: [PATCH] feat(url): add logout url constructor --- pkg/url/url.go | 12 ++++++++++++ pkg/url/url_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/pkg/url/url.go b/pkg/url/url.go index f63238e..f033bbb 100644 --- a/pkg/url/url.go +++ b/pkg/url/url.go @@ -40,6 +40,18 @@ func LoginRelative(prefix, redirect string) string { return Login(u, redirect) } +// Logout constructs a URL string that points to the logout path for the given target URL. +// The given redirect string should point to the location to be redirected to after logout. +func Logout(target *url.URL, redirect string) string { + u := target.JoinPath(paths.OAuth2, paths.Logout) + + v := u.Query() + v.Set(RedirectQueryParameter, redirect) + u.RawQuery = v.Encode() + + return u.String() +} + func LoginCallback(r *http.Request) (string, error) { return makeCallbackURL(r, paths.LoginCallback) } diff --git a/pkg/url/url_test.go b/pkg/url/url_test.go index 2afbc96..21f658b 100644 --- a/pkg/url/url_test.go +++ b/pkg/url/url_test.go @@ -91,6 +91,48 @@ func TestLoginRelative(t *testing.T) { } } +func TestLogout(t *testing.T) { + for _, test := range []struct { + name string + targetURL string + redirectTarget string + want string + }{ + { + name: "root path", + targetURL: "https://sso.wonderwall", + redirectTarget: "https://test.example.com?some=param&other=param2", + want: "https://sso.wonderwall/oauth2/logout?redirect=https%3A%2F%2Ftest.example.com%3Fsome%3Dparam%26other%3Dparam2", + }, + { + name: "with prefix", + targetURL: "https://sso.wonderwall/path", + redirectTarget: "https://test.example.com?some=param&other=param2", + want: "https://sso.wonderwall/path/oauth2/logout?redirect=https%3A%2F%2Ftest.example.com%3Fsome%3Dparam%26other%3Dparam2", + }, + { + name: "we need to go deeper", + targetURL: "https://sso.wonderwall/deeper/path", + redirectTarget: "https://test.example.com?some=param&other=param2", + want: "https://sso.wonderwall/deeper/path/oauth2/logout?redirect=https%3A%2F%2Ftest.example.com%3Fsome%3Dparam%26other%3Dparam2", + }, + { + name: "relative redirect target", + targetURL: "https://sso.wonderwall", + redirectTarget: "/path?some=param&other=param2", + want: "https://sso.wonderwall/oauth2/logout?redirect=%2Fpath%3Fsome%3Dparam%26other%3Dparam2", + }, + } { + t.Run(test.name, func(t *testing.T) { + targetURL, err := url.Parse(test.targetURL) + assert.NoError(t, err) + + logoutUrl := urlpkg.Logout(targetURL, test.redirectTarget) + assert.Equal(t, test.want, logoutUrl) + }) + } +} + func TestLoginCallback(t *testing.T) { cfg := mock.Config() cfg.Ingresses = []string{