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 或 false

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Request a new client token via the client_credentials grant before retrying
  2. Cache the client token with its expires-in and refresh it before expiry instead of hardcoding
  3. 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

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.