package usecase import ( "crypto/sha256" "encoding/hex" "fmt" "time" "backend/pkg/permission/domain/entity" "github.com/golang-jwt/jwt/v4" ) var accessTokenGenerator = createAccessToken var refreshTokenGenerator = createRefreshToken // createAccessToken 生成訪問令牌(Access Token) func createAccessToken(token entity.Token, data any, secretKey string) (string, error) { claims := 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, claims). SignedString([]byte(secretKey)) if err != nil { return "", err } return accessToken, nil } // createRefreshToken 基於訪問令牌生成刷新令牌(Refresh Token) func createRefreshToken(accessToken string) string { hash := sha256.New() _, _ = hash.Write([]byte(accessToken)) return hex.EncodeToString(hash.Sum(nil)) } func parseToken(accessToken string, secret string, validate bool) (jwt.MapClaims, error) { // 跳過驗證的解析 var token *jwt.Token var err error if validate { token, err = jwt.Parse(accessToken, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("token unexpected signing method: %v", token.Header["alg"]) } return []byte(secret), nil }) if err != nil { return jwt.MapClaims{}, err } } else { parser := jwt.NewParser(jwt.WithoutClaimsValidation()) token, err = parser.Parse(accessToken, func(_ *jwt.Token) (any, error) { return []byte(secret), nil }) if err != nil { return jwt.MapClaims{}, err } } claims, ok := token.Claims.(jwt.MapClaims) if !ok && token.Valid { return jwt.MapClaims{}, fmt.Errorf("token valid error") } return claims, nil } func parseClaims(accessToken string, secret string, validate bool) (tokenClaims, error) { claimMap, err := parseToken(accessToken, secret, validate) if err != nil { return tokenClaims{}, err } claimsData, ok := claimMap["data"].(map[string]any) if ok { return convertMap(claimsData), nil } return tokenClaims{}, fmt.Errorf("get data from claim map error") } 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 }