dromara/Sa-Token · error · SaOAuth2Exception

30103

30103

Error message

redirect_uri 不可为空

What it means

Thrown by RequestAuthModel.checkModel() when redirectUri is empty. The redirect_uri is mandatory in the authorize flow because the server must send the code/token back to the client. Error code 30103.

Source

Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/data/model/request/RequestAuthModel.java:195

	 */
	public RequestAuthModel setNonce(String nonce) {
		this.nonce = nonce;
		return this;
	}

	/**
	 * 数据自检
	 * @return 对象自身
	 */
	public RequestAuthModel checkModel() {
		if(SaFoxUtil.isEmpty(clientId)) {
			throw new SaOAuth2Exception("client_id 不可为空").setCode(SaOAuth2ErrorCode.CODE_30101);
		}
		if(SaFoxUtil.isEmpty(scopes)) {
			throw new SaOAuth2Exception("scope 不可为空").setCode(SaOAuth2ErrorCode.CODE_30102);
		}
		if(SaFoxUtil.isEmpty(redirectUri)) {
			throw new SaOAuth2Exception("redirect_uri 不可为空").setCode(SaOAuth2ErrorCode.CODE_30103);
		}
		if(SaFoxUtil.isEmpty(String.valueOf(loginId))) {
			throw new SaOAuth2Exception("LoginId 不可为空").setCode(SaOAuth2ErrorCode.CODE_30104);
		}
		return this;
	}

	@Override
	public String toString() {
		return "RequestAuthModel{" +
				"clientId='" + clientId + '\'' +
				", scopes=" + scopes +
				", loginId=" + loginId +
				", redirectUri='" + redirectUri + '\'' +
				", responseType='" + responseType + '\'' +
				", state='" + state + '\'' +
				", nonce='" + nonce + '\'' +
				'}';

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Include a redirect_uri in the authorize request that exactly matches one registered in the client's allowUrl list
  2. In custom grant handlers, set a placeholder redirectUri on the RequestAuthModel if the flow does not use redirects, or bypass the full checkModel()
  3. Verify URL encoding of the redirect_uri parameter so it is not lost during transport

Example fix

// before
ra.clientId = clientId;
ra.loginId = loginId;
ra.scopes = scopes;
ra.checkModel(); // throws 30103

// after
ra.clientId = clientId;
ra.loginId = loginId;
ra.scopes = scopes;
ra.redirectUri = "http://client.example.com/callback";
ra.checkModel();
Defensive patterns

Strategy: validation

Validate before calling

if(SaFoxUtil.isEmpty(redirectUri)) {
    throw new IllegalArgumentException("redirect_uri is required for authorize flow");
}

Try / catch

catch(SaOAuth2Exception e) { if("30103".equals(e.getCode())) return badRequest("redirect_uri required"); }

Prevention

When it happens

Trigger: Calling /oauth2/authorize with response_type=code but no redirect_uri parameter; manually building RequestAuthModel for token generation without setting redirectUri and calling checkModel().

Common situations: Client app configured an incomplete authorize URL; developer assumes redirect_uri registered on the client is enough and omits it from the request; custom password-grant code path reuses checkModel() even though password grant does not need a redirect.

Related errors


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