Compare commits

..

2 Commits

Author SHA1 Message Date
Justin Judd
941c56e69e feat(jwt): Enable using User Properties as custom claims (#3571) 2025-08-02 10:34:11 +08:00
DacongDA
a28b871a46 feat: add useGroupPathInToken boolean field in app.conf (#4026) 2025-08-02 01:40:26 +08:00
2 changed files with 84 additions and 4 deletions

View File

@@ -20,6 +20,7 @@ import (
"strings"
"time"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
"github.com/golang-jwt/jwt/v5"
)
@@ -341,10 +342,31 @@ func getClaimsCustom(claims Claims, tokenField []string) jwt.MapClaims {
res["provider"] = claims.Provider
for _, field := range tokenField {
userField := userValue.FieldByName(field)
if userField.IsValid() {
newfield := util.SnakeToCamel(util.CamelToSnakeCase(field))
res[newfield] = userField.Interface()
if strings.HasPrefix(field, "Properties") {
/*
Use selected properties fields as custom claims.
Converts `Properties.my_field` to custom claim with name `my_field`.
*/
parts := strings.Split(field, ".")
if len(parts) != 2 || parts[0] != "Properties" { // Either too many segments, or not properly scoped to `Properties`, so skip.
continue
}
base, fieldName := parts[0], parts[1]
mField := userValue.FieldByName(base)
if !mField.IsValid() { // Can't find `Properties` field, so skip.
continue
}
finalField := mField.MapIndex(reflect.ValueOf(fieldName))
if finalField.IsValid() { // // Provided field within `Properties` exists, add claim.
res[fieldName] = finalField.Interface()
}
} else { // Use selected user field as claims.
userField := userValue.FieldByName(field)
if userField.IsValid() {
newfield := util.SnakeToCamel(util.CamelToSnakeCase(field))
res[newfield] = userField.Interface()
}
}
}
@@ -381,6 +403,14 @@ func generateJwtToken(application *Application, user *User, provider string, non
refreshExpireTime = expireTime
}
if conf.GetConfigBool("useGroupPathInToken") {
groupPath, err := user.GetUserFullGroupPath()
if err != nil {
return "", "", "", err
}
user.Groups = groupPath
}
user = refineUser(user)
_, originBackend := getOriginFromHost(host)

View File

@@ -1331,6 +1331,56 @@ func (user *User) CheckUserFace(faceIdImage []string, provider *Provider) (bool,
return false, nil
}
func (user *User) GetUserFullGroupPath() ([]string, error) {
if len(user.Groups) == 0 {
return []string{}, nil
}
var orgGroups []*Group
orgGroups, err := GetGroups(user.Owner)
if err != nil {
return nil, err
}
groupMap := make(map[string]Group)
for _, group := range orgGroups {
groupMap[group.Name] = *group
}
var groupFullPath []string
for _, groupId := range user.Groups {
_, groupName := util.GetOwnerAndNameFromIdNoCheck(groupId)
group, ok := groupMap[groupName]
if !ok {
continue
}
groupPath := groupName
curGroup, ok := groupMap[group.ParentId]
if !ok {
return []string{}, fmt.Errorf("group:Group %s not exist", group.ParentId)
}
for {
groupPath = util.GetId(curGroup.Name, groupPath)
if curGroup.IsTopGroup {
break
}
curGroup, ok = groupMap[curGroup.ParentId]
if !ok {
return []string{}, fmt.Errorf("group:Group %s not exist", curGroup.ParentId)
}
}
groupPath = util.GetId(curGroup.Owner, groupPath)
groupFullPath = append(groupFullPath, groupPath)
}
return groupFullPath, nil
}
func GenerateIdForNewUser(application *Application) (string, error) {
if application == nil || application.GetSignupItemRule("ID") != "Incremental" {
return util.GenerateId(), nil