dromara/Sa-Token · error · SaOAuth2ClientModelException

30114

30114

Error message

非法 redirect_url: 

What it means

Thrown when the (query-stripped) redirect_uri is not present in the client's configured allowRedirectUris list (code 30114). sa-token matches the URL against the client's registered allow-list before issuing a code; exact or wildcard-suffix entries match, anything else is rejected as '非法 redirect_url'.

Source

Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Template.java:195

			//       http://sa-token.com/?code=i8vDfbpqBViMe01QoLY1kHROJWYvv9plBtvTZ6kk77KK0e0U4Xj99NPfSZEYjRul
			//
			//  造成了 code 参数劫持
			//  所以此处需要禁止在 url 中出现 @ 字符
			//
			//  这么一刀切的做法,可能会导致一些特殊的正常url也无法通过校验,例如:
			//       http://sa-oauth-server.com:8000/oauth2/authorize?response_type=code&client_id=1001&redirect_uri=http://sa-oauth-client.com/@getInfo
			//
			//  但是为了安全起见,这么做还是有必要的
			throw new SaOAuth2ClientModelException("无效 redirect_url(不允许出现@字符):" + url)
					.setClientId(clientId)
					.setCode(SaOAuth2ErrorCode.CODE_30113);
		}

		// 4、是否在[允许地址列表]之中
		SaClientModel clientModel = checkClientModel(clientId);
		checkRedirectUriListNormal(clientModel.allowRedirectUris);
		if( ! SaStrategy.instance.hasElement.apply(clientModel.allowRedirectUris, url)) {
			throw new SaOAuth2ClientModelException("非法 redirect_url: " + url)
					.setClientId(clientId)
					.setCode(SaOAuth2ErrorCode.CODE_30114);
		}
	}

	/**
	 * 校验配置的 allowRedirectUris 是否合规,如果不合规则抛出异常
	 * @param redirectUriList 待校验的 allow-url 地址列表
	 */
	public void checkRedirectUriListNormal(List<String> redirectUriList){
		checkRedirectUriListNormalStaticMethod(redirectUriList);
	}

	/**
	 * 校验配置的 allowRedirectUris 是否合规,如果不合规则抛出异常,静态方法内部实现
	 * @param redirectUriList 待校验的 allow-url 地址列表
	 */
	public static void checkRedirectUriListNormalStaticMethod(List<String> redirectUriList){

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Add the exact redirect_uri to the client's allow-url configuration (sa-token style: putAllowUrl or config in the client register list)
  2. Fix scheme/port/path mismatches in the redirect_uri so it matches an existing allow entry
  3. Use a trailing '*' wildcard entry (e.g. http://client.com/*) only at the end, to cover multiple callback paths

Example fix

// before
new SaClientModel().setClientId("1001").setAllowUrl("http://sa-oauth-client.com/callback");
// redirect_uri=http://sa-oauth-client.com:8000/callback -> rejected
// after
new SaClientModel().setClientId("1001").setAllowUrl("http://sa-oauth-client.com/callback", "http://sa-oauth-client.com:8000/callback");
Defensive patterns

Strategy: validation

Validate before calling

String stripped = url.split("\\?")[0];
boolean allowed = SaStrategy.instance.hasElement.apply(client.getAllowRedirectUris(), stripped);
if (!allowed) throw new IllegalArgumentException("redirect_uri not in allow list: " + stripped);

Try / catch

try { saOAuth2Template.checkRedirectUri(clientId, url); } catch (SaOAuth2ClientModelException e) { if (e.getCode() == 30114) return badRequest("redirect_uri not registered"); throw e; }

Prevention

When it happens

Trigger: Calling /oauth2/authorize with a redirect_uri whose scheme, host, port, or path differs from every entry in the client's allowRedirectUris (e.g. http vs https, missing port :8000, different path, trailing slash mismatch).

Common situations: Client app moved to a new domain or port but allow-url config was not updated; http/https mismatch behind a TLS-terminating proxy; trailing-slash or context-path differences; wildcard entry 'http://client.com/*' not matching a different subdomain.

Related errors


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