dromara/Sa-Token · error · SaOAuth2ClientModelException
30113
30113
Error message
无效 redirect_url:
What it means
Thrown by SaOAuth2Template.checkRedirectUri when the redirect_uri passed to the OAuth2 authorize endpoint is not a syntactically valid URL (SaFoxUtil.isUrl fails). The library validates the callback URL before issuing an authorization code, because the redirect_uri is where the code gets delivered; an unparseable value cannot be trusted or matched. Error code is 30113 and the offending URL is appended to the message.
Source
Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Template.java:153
.setClientId(cm.clientId)
.setScope(scope)
.setCode(SaOAuth2ErrorCode.CODE_30112);
}
}
return cm;
}
// --------- redirect_uri 相关
/**
* 校验:该 Client 使用指定 url 作为回调地址,是否合法
* @param clientId 应用id
* @param url 指定url
*/
public void checkRedirectUri(String clientId, String url) {
// 1、是否是一个有效的url
if( ! SaFoxUtil.isUrl(url)) {
throw new SaOAuth2ClientModelException("无效 redirect_url:" + url)
.setClientId(clientId)
.setCode(SaOAuth2ErrorCode.CODE_30113);
}
// 2、截取掉?后面的部分
int qIndex = url.indexOf("?");
if(qIndex != -1) {
url = url.substring(0, qIndex);
}
// 3、不允许出现@字符
if(url.contains("@")) {
// 为什么不允许出现 @ 字符呢,因为这有可能导致 redirect_url 参数绕过 AllowUrl 列表的校验
//
// 举个例子 SaClientModel 配置:
// allow-url=http://sa-oauth-client.com*
//
// 开发者原意是为了允许 sa-oauth-client.com 下的所有地址都可以下放 codeView on GitHub (pinned to ac2c7f6e94)
Solutions
- Ensure redirect_uri is an absolute URL with scheme and host, e.g. http://client.example.com/callback
- URL-encode the redirect_uri when constructing the authorize link so '&' or '=' inside it survive transport
- Verify no gateway/filter strips or rewrites the redirect_uri request parameter before it reaches the OAuth2 module
Example fix
// before String url = server + "/oauth2/authorize?response_type=code&client_id=1001&redirect_uri=" + callback; // after String url = server + "/oauth2/authorize?response_type=code&client_id=1001&redirect_uri=" + URLEncoder.encode(callback, "UTF-8");
Defensive patterns
Strategy: validation
Validate before calling
boolean ok = redirectUri != null && java.util.regex.Pattern.matches("^https?://[\\w.-]+(:\\d+)?(/.*)?$", redirectUri);
if (!ok) throw new IllegalArgumentException("redirect_uri must be an absolute http(s) URL: " + redirectUri); Try / catch
try { saOAuth2Template.checkRedirectUri(clientId, url); } catch (SaOAuth2ClientModelException e) { if (e.getCode() == 30113) return badRequest("invalid redirect_uri"); throw e; } Prevention
- Centralize authorize-URL construction in one helper that always URL-encodes redirect_uri
- Validate redirect_uri format on the client before navigating to the authorize endpoint
When it happens
Trigger: Calling the /oauth2/authorize endpoint with a missing, empty, or malformed redirect_uri parameter (e.g. 'redirect_uri=abc', a relative path, or a value without scheme) for a registered client.
Common situations: Front-end builds the authorize link by hand and URL-encodes the redirect_uri incorrectly, or omits it entirely; a proxy/gateway strips query parameters; environment config differences between test and prod supply an incomplete URL.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/2d1c331e0684a79c.
Report an issue: GitHub.