justauth/JustAuth · error · AuthException

${subMsg}

Error message

${subMsg}

What it means

After certificateExecute returns, AuthAlipayCertRequest.getAccessToken checks response.isSuccess(); on failure it throws AuthException with the response's subMsg — Alipay's own business-error description (e.g. invalid code, wrong grant type, app not authorized for the oauth API). This is a rejected token exchange, i.e. Alipay processed the request and said no.

Source

Thrown at src/main/java/me/zhyd/oauth/request/AuthAlipayCertRequest.java:63

    protected void checkCode(AuthCallback authCallback) {
        if (StringUtils.isEmpty(authCallback.getAuth_code())) {
            throw new AuthException(AuthResponseStatus.ILLEGAL_CODE, source);
        }
    }

    @Override
    public AuthToken getAccessToken(AuthCallback authCallback) {
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(authCallback.getAuth_code());
        AlipaySystemOauthTokenResponse response;
        try {
            response = this.alipayClient.certificateExecute(request);
        } catch (Exception e) {
            throw new AuthException(e);
        }
        if (!response.isSuccess()) {
            throw new AuthException(response.getSubMsg());
        }
        return AuthToken.builder()
            .accessToken(response.getAccessToken())
            .uid(response.getUserId())
            .expireIn(Integer.parseInt(response.getExpiresIn()))
            .refreshToken(response.getRefreshToken())
            .build();
    }


    /**
     * 刷新access token (续期)
     *
     * @param authToken 登录成功后返回的Token信息
     * @return AuthResponse
     */
    @Override
    public AuthResponse<AuthToken> refresh(AuthToken authToken) {

View on GitHub (pinned to 694bbf1b01)

Solutions

  1. Read subMsg literally (e.g. '无效的授权码' = auth_code invalid/consumed) and match to the fix: re-authorize the user instead of reusing the code.
  2. Confirm the Alipay open-platform app has the user-info product signed and the gateway environment (sandbox/prod) matches the credentials.
  3. Ensure AuthConfig.clientId equals the appId that generated the auth_code.
  4. Process the callback exactly once; make the token exchange idempotent by storing the resulting token keyed on code.

Example fix

// before
// user re-opens the callback URL -> same auth_code exchanged twice -> subMsg exception

// after
// idempotent callback: key on auth_code
AuthToken cached = tokenStore.byCode(cb.getAuth_code());
if (cached != null) return ok(cached);
AuthToken t = request.getAccessToken(cb); tokenStore.save(cb.getAuth_code(), t); return ok(t);
Defensive patterns

Strategy: try-catch

Validate before calling

// idempotency guard: never exchange the same auth_code twice
if (tokenStore.find(cb.getAuth_code()) != null) { return ok(tokenStore.find(cb.getAuth_code())); }

Try / catch

try { return request.getAccessToken(cb); } catch (AuthException e) { log.warn("Alipay rejected token exchange: {}", e.getMessage()); return restartAlipayAuthorize(); }

Prevention

When it happens

Trigger: Exchanging an auth_code that was already used or expired; the app lacks the 获取会员信息 (user info) capability or is_au not enabled so AlipaySystemOauthTokenRequest is refused; app_id mismatch between the code's app and the configured app; refresh-style grant on a code grant request.

Common situations: User refreshes the callback URL causing code reuse; Alipay app not signed/approved for the oauth scope in production while it worked in sandbox; wrong appId in AuthConfig relative to the app that issued the code.

Related errors


AI-assisted analysis of justauth/JustAuth@694bbf1b01 (2026-08-14). Data as JSON: /api/errors/9a50ab2d4d43392f. Report an issue: GitHub.