dromara/Sa-Token · error · SaSsoException
CODE_30005
CODE_30005
Error message
{result.getMsg()} What it means
Thrown during ticket validation (SSO mode 2/3): the client sent a check-ticket message to the sso-server and the response's code was not 200. The exception carries the server's msg, so the actual failure reason (invalid ticket, bad sign, missing client config) is whatever the server replied.
Source
Thrown at sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/processor/SaSsoClientProcessor.java:357
if(SaFoxUtil.isNotEmpty(cfg.getCurrSsoLogoutCall())) {
ssoLogoutCall = cfg.getCurrSsoLogoutCall();
}
// 如果提供了当前 uri,则根据此值来计算:
else if(SaFoxUtil.isNotEmpty(currUri)) {
ssoLogoutCall = SaHolder.getRequest().getUrl().replace(currUri, apiName.ssoLogoutCall);
}
// 否则视为不注册单点注销回调地址
else {
}
}
// 发起请求
SaSsoMessage message = ssoClientTemplate.buildCheckTicketMessage(ticket, ssoLogoutCall);
SaResult result = ssoClientTemplate.pushMessageAsSaResult(message);
// 如果 sso-server 响应的状态码非200,代表业务失败,将回应的 msg 字段作为异常抛出
if(result.getCode() == null || result.getCode() != SaResult.CODE_SUCCESS) {
throw new SaSsoException(result.getMsg()).setCode(SaSsoErrorCode.CODE_30005);
}
// 构建返回结果
SaCheckTicketResult ctr = new SaCheckTicketResult();
ctr.loginId = result.get(paramName.loginId);
ctr.tokenValue = result.get(paramName.tokenValue, String.class);
ctr.deviceId = result.get(paramName.deviceId, String.class);
ctr.remainTokenTimeout = result.get(paramName.remainTokenTimeout, Long.class);
ctr.remainSessionTimeout = result.get(paramName.remainSessionTimeout, Long.class);
ctr.result = result;
// 转换 loginId 和 centerId
ctr.centerId = ctr.loginId;
ctr.loginId = ssoClientTemplate.strategy.convertCenterIdToLoginId.run(ctr.centerId);
return ctr;
}
View on GitHub (pinned to ac2c7f6e94)
Solutions
- Inspect the exact msg string — it mirrors the sso-server's error (invalid ticket vs sign error vs client not configured)
- Ensure the ticket is validated only once and immediately after redirect (tickets are one-time use in checkTicketParamAndDelete)
- Verify secret-key, server-url and client identifier match between the two sides
Defensive patterns
Strategy: try-catch
Try / catch
try {
SaCheckTicketResult r = ssoClientTemplate.checkTicket(ticket);
} catch (SaSsoException e) {
if(SaSsoErrorCode.CODE_30005 == e.getCode()) {
// rethrow result.getMsg(); typically redirect back to /sso/auth to reissue ticket
}
} Prevention
- Never re-validate the same ticket; consume it once on callback
- Check the propagated msg — it is the server's real failure reason
When it happens
Trigger: Client callback /sso/login?ticket=... invokes ssoClientTemplate.checkTicket(ticket); the pushMessageAsSaResult call for buildCheckTicketMessage returns a SaResult whose code != 200 (or code is null because the response was not a valid SaResult at all).
Common situations: Ticket already consumed or expired on the server; secret-key mismatch causing sign verification failure on the server; server URL misconfigured so the client hit a 404 page; a gateway/filter intercepting the server-to-server call.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/15a4e56da56aec4d.
Report an issue: GitHub.