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
- Include a redirect_uri in the authorize request that exactly matches one registered in the client's allowUrl list
- In custom grant handlers, set a placeholder redirectUri on the RequestAuthModel if the flow does not use redirects, or bypass the full checkModel()
- 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
- Always URL-encode redirect_uri exactly as registered
- In non-redirect grant handlers, populate a placeholder redirectUri before checkModel()
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.