From f9ed40b8e5d0393bb82d6e221facba91a8eebb01 Mon Sep 17 00:00:00 2001 From: MrMelon54 Date: Sun, 15 Oct 2023 13:49:58 +0100 Subject: [PATCH] Use internal scopes within FancyScopeList --- scope/scope.go | 43 ++++++------------------------------------ scope/scope_test.go | 16 ++++++++++++++++ server/manage-users.go | 2 +- server/oauth.go | 10 ++++++++-- 4 files changed, 31 insertions(+), 40 deletions(-) diff --git a/scope/scope.go b/scope/scope.go index df20e0d..acdbb69 100644 --- a/scope/scope.go +++ b/scope/scope.go @@ -26,44 +26,13 @@ func ScopesExist(scope string) bool { // FancyScopeList takes a scope string and outputs a slice of scope descriptions func FancyScopeList(scope string) (arr []string) { - seen := make(map[string]struct{}) -outer: - for { - n := strings.IndexAny(scope, ", ") - var key string - switch n { - case 0: - // first char is matching, no key name found, just continue - scope = scope[1:] - continue outer - case -1: - // no more matching chars, if scope is empty then we are done - if len(scope) == 0 { - return - } - - // otherwise set the key and empty scope - key = scope - scope = "" - default: - // set the key and trim from scope - key = scope[:n] - scope = scope[n+1:] - } - - // check if key has been seen already - if _, ok := seen[key]; ok { - continue outer - } - - // set seen flag - seen[key] = struct{}{} - - // output the description - if d := scopeDescription[key]; d != "" { - arr = append(arr, d) - } + a, err := internalGetScopes(scope, func(key, desc string) string { + return desc + }) + if err != nil { + return nil } + return a } func internalGetScopes(scope string, f func(key, desc string) string) (arr []string, err error) { diff --git a/scope/scope_test.go b/scope/scope_test.go index 6e04d11..7f32df2 100644 --- a/scope/scope_test.go +++ b/scope/scope_test.go @@ -5,6 +5,22 @@ import ( "testing" ) +func TestScopesExist(t *testing.T) { + desc := scopeDescription + scopeDescription = map[string]string{ + "a": "A", + "b": "B", + "c": "C", + } + + assert.True(t, ScopesExist("a b c")) + assert.False(t, ScopesExist("a b d")) + assert.True(t, ScopesExist("a,b c")) + assert.False(t, ScopesExist("a,b d")) + + scopeDescription = desc +} + func TestFancyScopeList(t *testing.T) { desc := scopeDescription scopeDescription = map[string]string{ diff --git a/server/manage-users.go b/server/manage-users.go index f7ec332..505d912 100644 --- a/server/manage-users.go +++ b/server/manage-users.go @@ -84,7 +84,7 @@ func (h *HttpServer) ManageUsersPost(rw http.ResponseWriter, req *http.Request, return } if role != database.RoleAdmin { - http.Error(rw, "400 Bad Request: Only admin users can create SSO client applications", http.StatusBadRequest) + http.Error(rw, "400 Bad Request: Only admin users can manage users", http.StatusBadRequest) return } diff --git a/server/oauth.go b/server/oauth.go index 3c98b21..fd971f2 100644 --- a/server/oauth.go +++ b/server/oauth.go @@ -93,19 +93,25 @@ func (h *HttpServer) authorizeEndpoint(rw http.ResponseWriter, req *http.Request return } + scopeList := form.Get("scope") + if !scope.ScopesExist(scopeList) { + http.Error(rw, "Invalid scopes", http.StatusBadRequest) + return + } + rw.WriteHeader(http.StatusOK) pages.RenderPageTemplate(rw, "oauth-authorize", map[string]any{ "ServiceName": h.conf.ServiceName, "AppName": appName, "AppDomain": appDomain, "User": user, - "WantsList": scope.FancyScopeList(form.Get("scope")), + "WantsList": scope.FancyScopeList(scopeList), "ResponseType": form.Get("response_type"), "ResponseMode": form.Get("response_mode"), "ClientID": form.Get("client_id"), "RedirectUri": form.Get("redirect_uri"), "State": form.Get("state"), - "Scope": form.Get("scope"), + "Scope": scopeList, "Nonce": form.Get("nonce"), "HasOtp": hasOtp, })