dromara/Sa-Token · error · SaOAuth2Exception

30126

30126

Error message

无效 grant_type:

What it means

Thrown by SaOAuth2ServerProcessor.clientToken: the client-credentials endpoint (/oauth2/client_token) requires grant_type=client_credentials exactly. Any other value (including authorization_code or password, which belong on /oauth2/token) is rejected before config and client checks run. Error code 30126.

Source

Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/processor/SaOAuth2ServerProcessor.java:301

		}

		// 默认返回
		throw new SaOAuth2Exception("无效response_type: " + ra.responseType).setCode(SaOAuth2ErrorCode.CODE_30125);
	}

	/**
	 * 模式四:凭证式
	 * @return 处理结果
	 */
	public Object clientToken() {
		// 获取变量
		SaRequest req = SaHolder.getRequest();
		SaOAuth2ServerConfig cfg = SaOAuth2Manager.getServerConfig();
		SaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();

		String grantType = req.getParamNotNull(Param.grant_type);
		if(!grantType.equals(GrantType.client_credentials)) {
			throw new SaOAuth2Exception("无效 grant_type:" + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
		}
		if(!cfg.enableClientCredentials) {
			throwErrorSystemNotEnableModel();
		}
		if(!currClientModel().getAllowGrantTypes().contains(GrantType.client_credentials)) {
			throwErrorClientNotEnableModel();
		}

		// 获取参数
		ClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
		String clientId = clientIdAndSecret.clientId;
		String clientSecret = clientIdAndSecret.clientSecret;
		List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(req.getParam(Param.scope));

		// 校验 ClientScope
		oauth2Template.checkContractScope(clientId, scopes);

		// 校验 ClientSecret

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Use grant_type=client_credentials on /oauth2/client_token
  2. For authorization_code or password grants, call /oauth2/token instead
  3. Trim and verify the exact spelling of grant_type before sending

Example fix

# before
curl -X POST http://host/oauth2/client_token -d 'grant_type=password&username=x&password=y'

# after
curl -X POST http://host/oauth2/client_token \
  -u 1001:secret -d 'grant_type=client_credentials&scope=all'
Defensive patterns

Strategy: validation

Validate before calling

if(!"client_credentials".equals(grantType)) {
    throw new IllegalArgumentException("/oauth2/client_token only accepts grant_type=client_credentials");
}

Try / catch

catch(SaOAuth2Exception e) { if("30126".equals(e.getCode())) return badRequest("invalid grant_type for this endpoint"); }

Prevention

When it happens

Trigger: POST /oauth2/client_token with grant_type=password or grant_type=authorization_code; grant_type missing or misspelled (e.g. 'clientcredential').

Common situations: Developer points all token requests at the wrong endpoint; copy-pasted token request from password flow reused against client_token; trailing whitespace in the parameter.

Related errors


AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14). Data as JSON: /api/errors/c682d3742c67370a. Report an issue: GitHub.