diff --git a/internal/integration/java.go b/internal/integration/java.go index cfd03fe..4315209 100644 --- a/internal/integration/java.go +++ b/internal/integration/java.go @@ -4,6 +4,7 @@ import ( "bytes" "chatapp3-golang/internal/config" "context" + "encoding/base64" "encoding/json" "fmt" "io" @@ -11,6 +12,7 @@ import ( "net/url" "strconv" "strings" + "time" ) type Client struct { @@ -19,8 +21,12 @@ type Client struct { } type UserCredential struct { - UserID Int64Value `json:"userId"` - SysOrigin string `json:"sysOrigin"` + UserID Int64Value `json:"userId"` + SysOrigin string `json:"sysOrigin"` + ExpireTime Int64Value `json:"expireTime"` + ReleaseTime Int64Value `json:"releaseTime"` + Version string `json:"version"` + Sign string `json:"sign"` } type UserProfile struct { @@ -113,7 +119,13 @@ func New(cfg config.Config) *Client { } func (c *Client) AuthenticateToken(ctx context.Context, token string) (UserCredential, error) { - endpoint := c.cfg.JavaAuthBaseURL + "/auth/client/getUserCredentialByToken?token=" + url.QueryEscape(token) + tokenCredential, err := parseUserCredentialToken(token) + if err != nil { + return UserCredential{}, err + } + + endpoint := c.cfg.JavaAuthBaseURL + "/auth/client/getUserCredential?userId=" + + url.QueryEscape(strconv.FormatInt(int64(tokenCredential.UserID), 10)) var resp resultResponse[UserCredential] if err := c.getJSON(ctx, endpoint, nil, &resp); err != nil { return UserCredential{}, err @@ -121,7 +133,73 @@ func (c *Client) AuthenticateToken(ctx context.Context, token string) (UserCrede if int64(resp.Body.UserID) == 0 { return UserCredential{}, fmt.Errorf("empty credential response") } - return resp.Body, nil + if strings.TrimSpace(resp.Body.Sign) == "" { + return UserCredential{}, fmt.Errorf("empty credential sign") + } + if !strings.EqualFold(strings.TrimSpace(resp.Body.Sign), strings.TrimSpace(tokenCredential.Sign)) { + return UserCredential{}, fmt.Errorf("credential sign mismatch") + } + if strings.TrimSpace(resp.Body.SysOrigin) != "" && !strings.EqualFold(resp.Body.SysOrigin, tokenCredential.SysOrigin) { + return UserCredential{}, fmt.Errorf("credential sysOrigin mismatch") + } + return tokenCredential, nil +} + +func parseUserCredentialToken(token string) (UserCredential, error) { + token = strings.TrimSpace(token) + if token == "" { + return UserCredential{}, fmt.Errorf("token is blank") + } + + parts := strings.SplitN(token, ".", 2) + if len(parts) != 2 { + return UserCredential{}, fmt.Errorf("invalid token format") + } + + sign := strings.TrimSpace(parts[0]) + if sign == "" { + return UserCredential{}, fmt.Errorf("invalid token sign") + } + + decoded, err := base64.StdEncoding.DecodeString(parts[1]) + if err != nil { + return UserCredential{}, fmt.Errorf("decode token payload: %w", err) + } + + payload, err := url.QueryUnescape(string(decoded)) + if err != nil { + return UserCredential{}, fmt.Errorf("unescape token payload: %w", err) + } + + items := strings.Split(payload, ":") + if len(items) != 5 { + return UserCredential{}, fmt.Errorf("invalid token payload") + } + + userID, err := strconv.ParseInt(strings.TrimSpace(items[1]), 10, 64) + if err != nil { + return UserCredential{}, fmt.Errorf("invalid token userId: %w", err) + } + expireTime, err := strconv.ParseInt(strings.TrimSpace(items[3]), 10, 64) + if err != nil { + return UserCredential{}, fmt.Errorf("invalid token expireTime: %w", err) + } + releaseTime, err := strconv.ParseInt(strings.TrimSpace(items[4]), 10, 64) + if err != nil { + return UserCredential{}, fmt.Errorf("invalid token releaseTime: %w", err) + } + if expireTime <= time.Now().UnixMilli() { + return UserCredential{}, fmt.Errorf("token expired") + } + + return UserCredential{ + UserID: Int64Value(userID), + SysOrigin: strings.TrimSpace(items[2]), + ExpireTime: Int64Value(expireTime), + ReleaseTime: Int64Value(releaseTime), + Version: strings.TrimSpace(items[0]), + Sign: sign, + }, nil } func (c *Client) GetDeviceFingerprint(ctx context.Context, userID int64) (string, error) {