mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-08 07:10:56 +03:00
OIDC: allow to get the role field from a sub-struct
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
@@ -225,12 +225,7 @@ func (t *oidcToken) parseClaims(claims map[string]any, usernameField, roleField
|
||||
if forcedRole != "" {
|
||||
t.Role = forcedRole
|
||||
} else {
|
||||
if roleField != "" {
|
||||
role, ok := claims[roleField]
|
||||
if ok {
|
||||
t.Role = role
|
||||
}
|
||||
}
|
||||
t.getRoleFromField(claims, roleField)
|
||||
}
|
||||
t.CustomFields = nil
|
||||
if len(customFields) > 0 {
|
||||
@@ -254,6 +249,41 @@ func (t *oidcToken) parseClaims(claims map[string]any, usernameField, roleField
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *oidcToken) getRoleFromField(claims map[string]any, roleField string) {
|
||||
if roleField != "" {
|
||||
role, ok := claims[roleField]
|
||||
if ok {
|
||||
t.Role = role
|
||||
return
|
||||
}
|
||||
if !strings.Contains(roleField, ".") {
|
||||
return
|
||||
}
|
||||
|
||||
getStructValue := func(outer any, field string) (any, bool) {
|
||||
switch val := outer.(type) {
|
||||
case map[string]any:
|
||||
res, ok := val[field]
|
||||
return res, ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
for idx, field := range strings.Split(roleField, ".") {
|
||||
if idx == 0 {
|
||||
role, ok = getStructValue(claims, field)
|
||||
} else {
|
||||
role, ok = getStructValue(role, field)
|
||||
}
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
t.Role = role
|
||||
}
|
||||
}
|
||||
|
||||
func (t *oidcToken) isAdmin() bool {
|
||||
switch v := t.Role.(type) {
|
||||
case string:
|
||||
|
||||
@@ -1156,6 +1156,7 @@ func TestOIDCIsAdmin(t *testing.T) {
|
||||
{input: append(emptySlice, 1), want: false},
|
||||
{input: 1, want: false},
|
||||
{input: nil, want: false},
|
||||
{input: map[string]string{"admin": "admin"}, want: false},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
token := oidcToken{
|
||||
@@ -1165,6 +1166,59 @@ func TestOIDCIsAdmin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAdminRole(t *testing.T) {
|
||||
claims := make(map[string]any)
|
||||
rawClaims := []byte(`{
|
||||
"sub": "35666371",
|
||||
"email": "example@example.com",
|
||||
"preferred_username": "Sally",
|
||||
"name": "Sally Tyler",
|
||||
"updated_at": "2018-04-13T22:08:45Z",
|
||||
"given_name": "Sally",
|
||||
"family_name": "Tyler",
|
||||
"params": {
|
||||
"sftpgo_role": "admin",
|
||||
"subparams": {
|
||||
"sftpgo_role": "admin",
|
||||
"inner": {
|
||||
"sftpgo_role": ["user","admin"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"at_hash": "lPLhxI2wjEndc-WfyroDZA",
|
||||
"rt_hash": "mCmxPtA04N-55AxlEUbq-A",
|
||||
"aud": "78d1d040-20c9-0136-5146-067351775fae92920",
|
||||
"exp": 1523664997,
|
||||
"iat": 1523657797
|
||||
}`)
|
||||
err := json.Unmarshal(rawClaims, &claims)
|
||||
assert.NoError(t, err)
|
||||
|
||||
type test struct {
|
||||
input string
|
||||
want bool
|
||||
}
|
||||
|
||||
tests := []test{
|
||||
{input: "sftpgo_role", want: false},
|
||||
{input: "params.sftpgo_role", want: true},
|
||||
{input: "params.subparams.sftpgo_role", want: true},
|
||||
{input: "params.subparams.inner.sftpgo_role", want: true},
|
||||
{input: "email", want: false},
|
||||
{input: "missing", want: false},
|
||||
{input: "params.email", want: false},
|
||||
{input: "missing.sftpgo_role", want: false},
|
||||
{input: "params", want: false},
|
||||
{input: "params.subparams.inner.sftpgo_role.missing", want: false},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
token := oidcToken{}
|
||||
token.getRoleFromField(claims, tc.input)
|
||||
assert.Equal(t, tc.want, token.isAdmin(), "%q should return %t", tc.input, tc.want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOIDCWithLoginFormsDisabled(t *testing.T) {
|
||||
oidcMgr, ok := oidcMgr.(*memoryOIDCManager)
|
||||
require.True(t, ok)
|
||||
|
||||
Reference in New Issue
Block a user