diff --git a/internal/app/auth/oauth_common.go b/internal/app/auth/oauth_common.go index e0b19c9..7f610e1 100644 --- a/internal/app/auth/oauth_common.go +++ b/internal/app/auth/oauth_common.go @@ -60,7 +60,8 @@ func getOauthFieldMapping(f config.OauthFields) config.OauthFields { Phone: "phone", Department: "department", }, - IsAdmin: "admin_flag", + IsAdmin: "admin_flag", + UserGroups: "", // by default, do not use user groups } if f.UserIdentifier != "" { defaultMap.UserIdentifier = f.UserIdentifier @@ -83,6 +84,9 @@ func getOauthFieldMapping(f config.OauthFields) config.OauthFields { if f.IsAdmin != "" { defaultMap.IsAdmin = f.IsAdmin } + if f.UserGroups != "" { + defaultMap.UserGroups = f.UserGroups + } return defaultMap } diff --git a/internal/app/auth/oauth_common_test.go b/internal/app/auth/oauth_common_test.go new file mode 100644 index 0000000..5213686 --- /dev/null +++ b/internal/app/auth/oauth_common_test.go @@ -0,0 +1,57 @@ +package auth + +import ( + "encoding/json" + "testing" + + "github.com/h44z/wg-portal/internal/config" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_parseOauthUserInfo(t *testing.T) { + userInfoStr := ` +{ + "at_hash": "REDACTED", + "aud": "REDACTED", + "c_hash": "REDACTED", + "email": "test@mydomain.net", + "email_verified": true, + "exp": 1737404259, + "groups": [ + "abuse@mydomain.net", + "postmaster@mydomain.net", + "wgportal-admins@mydomain.net" + ], + "iat": 1737317859, + "iss": "https://dex.mydomain.net", + "name": "Test User", + "nonce": "REDACTED", + "sub": "REDACTED" +} +` + + userInfo := map[string]interface{}{} + err := json.Unmarshal([]byte(userInfoStr), &userInfo) + require.NoError(t, err) + + fieldMapping := getOauthFieldMapping(config.OauthFields{ + BaseFields: config.BaseFields{ + UserIdentifier: "email", + Email: "email", + Firstname: "name", + Lastname: "family_name", + }, + UserGroups: "groups", + }) + adminMapping := &config.OauthAdminMapping{ + AdminGroupRegex: "^wgportal-admins@mydomain.net$", + } + + info, err := parseOauthUserInfo(fieldMapping, adminMapping, userInfo) + assert.NoError(t, err) + assert.True(t, info.IsAdmin) + assert.Equal(t, info.Firstname, "Test User") + assert.Equal(t, info.Lastname, "") + assert.Equal(t, info.Email, "test@mydomain.net") +} diff --git a/internal/util.go b/internal/util.go index e096abf..cd2d4bd 100644 --- a/internal/util.go +++ b/internal/util.go @@ -88,6 +88,17 @@ func MapDefaultStringSlice(m map[string]interface{}, key string, dflt []string) return dflt } else { switch v := tmp.(type) { + case []any: + result := make([]string, 0, len(v)) + for _, elem := range v { + switch vElem := elem.(type) { + case string: + result = append(result, vElem) + default: + result = append(result, fmt.Sprintf("%v", vElem)) + } + } + return result case []string: return v case string: