package tokenservicelogic import ( "ark-permission/internal/domain" "ark-permission/internal/entity" "bytes" "context" "crypto/sha256" "encoding/hex" "fmt" "github.com/golang-jwt/jwt/v4" "time" ) var generateAccessTokenFunc = generateAccessToken var generateRefreshTokenFunc = generateRefreshToken func generateAccessToken(token entity.Token, data any, sign string) (string, error) { claim := entity.Claims{ Data: data, RegisteredClaims: jwt.RegisteredClaims{ ID: token.ID, ExpiresAt: jwt.NewNumericDate(time.Unix(int64(token.ExpiresIn), 0)), Issuer: "permission", }, } accessToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claim). SignedString([]byte(sign)) if err != nil { return "", domain.TokenClaimError(err.Error()) } return accessToken, nil } func generateRefreshToken(accessToken string) string { buf := bytes.NewBufferString(accessToken) h := sha256.New() _, _ = h.Write(buf.Bytes()) return hex.EncodeToString(h.Sum(nil)) } func parseClaims(ctx context.Context, accessToken string, secret string) (claims, error) { claimMap, err := parseToken(accessToken, secret) if err != nil { return claims{}, err } claims, ok := claimMap["data"].(map[string]any) if ok { return convertMap(claims), nil } return nil, domain.TokenClaimError("get data from claim map error") } func parseToken(accessToken string, secret string) (jwt.MapClaims, error) { token, err := jwt.Parse(accessToken, func(token *jwt.Token) (any, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, domain.TokenUnexpectedSigningErr(fmt.Sprintf("token unexpected signing method: %v", token.Header["alg"])) } return []byte(secret), nil }) if err != nil { return jwt.MapClaims{}, err } claims, ok := token.Claims.(jwt.MapClaims) if !(ok && token.Valid) { return jwt.MapClaims{}, domain.TokenTokenValidateErr("token valid error") } return claims, nil } func convertMap(input map[string]interface{}) map[string]string { output := make(map[string]string) for key, value := range input { switch v := value.(type) { case string: output[key] = v case fmt.Stringer: output[key] = v.String() default: output[key] = fmt.Sprintf("%v", value) } } return output }