feat: support "JWT-Custom" to customize user properties inside access token (#2594)

* feat: add custom attribute to access token

* Update token_jwt.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
This commit is contained in:
SamYSF 2024-01-10 00:59:02 +08:00 committed by GitHub
parent a2d20fcb63
commit a2b9f9baaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -16,6 +16,7 @@ package object
import (
"fmt"
"reflect"
"time"
"github.com/casdoor/casdoor/util"
@ -270,6 +271,34 @@ func getClaimsWithoutThirdIdp(claims Claims) ClaimsWithoutThirdIdp {
return res
}
func getClaimsCustom(claims Claims, tokenField []string) jwt.MapClaims {
res := make(jwt.MapClaims)
userValue := reflect.ValueOf(claims.User).Elem()
res["iss"] = claims.RegisteredClaims.Issuer
res["sub"] = claims.RegisteredClaims.Subject
res["aud"] = claims.RegisteredClaims.Audience
res["exp"] = claims.RegisteredClaims.ExpiresAt
res["nbf"] = claims.RegisteredClaims.NotBefore
res["iat"] = claims.RegisteredClaims.IssuedAt
res["jti"] = claims.RegisteredClaims.ID
res["tokenType"] = claims.TokenType
res["nonce"] = claims.Nonce
res["tag"] = claims.Tag
res["scope"] = claims.Scope
for _, field := range tokenField {
userField := userValue.FieldByName(field)
if userField.IsValid() {
newfield := util.SnakeToCamel(util.CamelToSnakeCase(field))
res[newfield] = userField.Interface()
}
}
return res
}
func refineUser(user *User) *User {
user.Password = ""
@ -329,20 +358,30 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
var refreshToken *jwt.Token
// the JWT token length in "JWT-Empty" mode will be very short, as User object only has two properties: owner and name
if application.TokenFormat == "JWT-Empty" {
claimsShort := getShortClaims(claims)
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
claimsShort.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
claimsShort.TokenType = "refresh-token"
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
} else {
if application.TokenFormat == "JWT" {
claimsWithoutThirdIdp := getClaimsWithoutThirdIdp(claims)
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsWithoutThirdIdp)
claimsWithoutThirdIdp.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
claimsWithoutThirdIdp.TokenType = "refresh-token"
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsWithoutThirdIdp)
} else if application.TokenFormat == "JWT-Empty" {
claimsShort := getShortClaims(claims)
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
claimsShort.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
claimsShort.TokenType = "refresh-token"
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
} else if application.TokenFormat == "JWT-Custom" {
claimsCustom := getClaimsCustom(claims, application.TokenFields)
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsCustom)
refreshClaims := getClaimsCustom(claims, application.TokenFields)
refreshClaims["exp"] = jwt.NewNumericDate(refreshExpireTime)
refreshClaims["TokenType"] = "refresh-token"
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, refreshClaims)
} else {
return "", "", "", fmt.Errorf("unknown application TokenFormat: %s", application.TokenFormat)
}
cert, err := getCertByApplication(application)