dromara/Sa-Token · error · SaOAuth2ClientTokenException
30107
30107
Error message
无效 client_token:
What it means
Thrown by SaOAuth2Template.checkClientToken when the client token lookup returns null (code 30107, SaOAuth2ClientTokenException). Client tokens are issued via the client_credentials grant for application-to-application calls; a miss means unknown, expired, or revoked token.
Source
Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Template.java:642
/**
* 获取 ClientTokenModel,无效的 ClientToken 会返回 null
* @param clientToken /
* @return /
*/
public ClientTokenModel getClientToken(String clientToken) {
return SaOAuth2Manager.getDao().getClientToken(clientToken);
}
/**
* 校验 Client-Token,成功返回 ClientTokenModel,失败则抛出异常
* @param clientToken /
* @return /
*/
public ClientTokenModel checkClientToken(String clientToken) {
ClientTokenModel ct = getClientToken(clientToken);
if(ct == null) {
throw new SaOAuth2ClientTokenException("无效 client_token: " + clientToken)
.setClientToken(clientToken)
.setCode(SaOAuth2ErrorCode.CODE_30107);
}
return ct;
}
/**
* 获取 Client-Token 列表:此应用下 对 某个用户 签发的所有 Client-token
*
* @param clientId /
* @return /
*/
public List<String> getClientTokenValueList(String clientId) {
return SaOAuth2Manager.getDao().getClientTokenValueList_FromAdjustAfter(clientId);
}
/**
* 判断:指定 Client-Token 是否具有指定 Scope 列表,返回 true 或 falseView on GitHub (pinned to ac2c7f6e94)
Solutions
- Request a new client token via the client_credentials grant before retrying
- Cache the client token with its expires-in and refresh it before expiry instead of hardcoding
- Confirm the parameter name/header the server expects (clientToken / satoken) and share the DAO across nodes
Defensive patterns
Strategy: retry
Validate before calling
if (saOAuth2Template.getClientToken(cachedToken) == null) { cachedToken = requestNewClientToken(); } Try / catch
try { saOAuth2Template.checkClientToken(token); } catch (SaOAuth2ClientTokenException e) { token = requestClientCredentialsToken(); retryOnce(request); } Prevention
- Cache client tokens with their TTL and refresh ahead of expiry
- Never hardcode a client token in configuration
When it happens
Trigger: Calling /oauth2/token?grant_type=client_credentials succeeds then the token expires, or an API protected by checkClientToken receives a missing/garbled/fabricated clientToken parameter.
Common situations: Client-token timeout is short and the calling service caches the token beyond expiry; token not propagated through a gateway; in-memory DAO lost on restart; caller sends access token where client token is required.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/ad042a6937889c7d.
Report an issue: GitHub.