fix(sign-session): add join_token to GetSignSessionByInviteCode API

The sign session flow was failing with "invalid token" error because
the GetSignSessionByInviteCode API did not return a join_token, unlike
the keygen GetSessionByInviteCode API.

Changes:
- Account Service: Generate wildcard JWT join token in GetSignSessionByInviteCode
- service-party-app: Update types and handlers to include joinToken in session
- service-party-app: Pass joinToken when joining sign session

This makes the sign flow consistent with the keygen flow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-30 06:31:41 -08:00
parent 33e972ce02
commit 32362b0ac2
5 changed files with 27 additions and 1 deletions

View File

@ -664,10 +664,30 @@ func (h *CoManagedHTTPHandler) GetSignSessionByInviteCode(c *gin.Context) {
return
}
// Generate a wildcard join token for this session
// This allows any participant to join using this token
var joinToken string
if h.jwtService != nil {
sessionUUID, err := uuid.Parse(sessionID)
if err == nil {
// Token valid until session expires
tokenExpiry := time.Until(expiresAt)
if tokenExpiry > 0 {
joinToken, err = h.jwtService.GenerateJoinToken(sessionUUID, "*", tokenExpiry)
if err != nil {
logger.Warn("Failed to generate join token for sign session",
zap.String("session_id", sessionID),
zap.Error(err))
}
}
}
}
logger.Info("Found sign session for invite_code",
zap.String("invite_code", inviteCode),
zap.String("session_id", sessionID),
zap.String("wallet_name", walletName))
zap.String("wallet_name", walletName),
zap.Bool("has_join_token", joinToken != ""))
c.JSON(http.StatusOK, gin.H{
"session_id": sessionID,
@ -679,5 +699,6 @@ func (h *CoManagedHTTPHandler) GetSignSessionByInviteCode(c *gin.Context) {
"completed_parties": statusResp.CompletedParties,
"total_parties": statusResp.TotalParties,
"expires_at": expiresAt.UnixMilli(),
"join_token": joinToken,
})
}

View File

@ -1073,6 +1073,7 @@ function setupIpcHandlers() {
currentParticipants: result?.joined_count || 0,
status: result?.status,
parties: result?.parties,
joinToken: result?.join_token,
},
};
} catch (error) {

View File

@ -137,6 +137,7 @@ export interface GetSignSessionByInviteCodeResponse {
expires_at: number;
parties: SignPartyInfo[];
joined_count: number;
join_token?: string;
}
// 错误响应

View File

@ -20,6 +20,7 @@ interface SigningSession {
threshold: { t: number; n: number };
currentParticipants: number;
initiator: string;
joinToken?: string;
}
export default function Sign() {
@ -135,6 +136,7 @@ export default function Sign() {
sessionId: signingSession!.sessionId,
shareId: selectedShare.id,
password: password,
joinToken: signingSession!.joinToken,
});
if (result.success) {

View File

@ -179,6 +179,7 @@ interface SigningSession {
threshold: { t: number; n: number };
currentParticipants: number;
initiator: string;
joinToken?: string;
}
interface ValidateSigningSessionResult {