justauth/JustAuth · error · AuthException

${subMsg}

Error message

${subMsg}

What it means

Thrown when Alipay returns a non-success AlipaySystemOauthTokenResponse during the authorization-code exchange (grant_type=authorization_code) in public-key mode. The message is Alipay's subMsg, e.g. 'invalid code' or 'code been used'.

Source

Thrown at src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java:161

    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.execute(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) {
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();

View on GitHub (pinned to 694bbf1b01)

Solutions

  1. Never exchange the same auth_code twice — if the first exchange may have succeeded, persist the token instead of retrying the exchange
  2. Process the callback immediately; Alipay auth codes expire in about 5 minutes
  3. Ensure the appId/redirectUri used at authorize time matches the one at token-exchange time
  4. Check the subMsg: 'aop.INVALID_CODE' or 'auth code is invalid' means re-authorization is required
Defensive patterns

Strategy: try-catch

Validate before calling

if (StringUtils.isEmpty(callback.getAuth_code())) {
    throw new IllegalStateException("missing auth_code — cannot exchange");
}
long ageMs = System.currentTimeMillis() - callbackReceivedAt;
if (ageMs > 4 * 60 * 1000) {
    // Alipay auth codes expire ~5 min; re-authorize instead of exchanging
    return redirectToAuthorize(ALIPAY);
}

Try / catch

try {
    return alipayRequest.getAccessToken(callback);
} catch (AuthException e) {
    if (e.getMessage() != null && e.getMessage().toLowerCase().contains("code")) {
        // code used/expired — cannot recover; new authorization required
        return redirectToAuthorize(ALIPAY);
    }
    throw e;
}

Prevention

When it happens

Trigger: AuthAlipayRequest.getAccessToken with an auth_code that is expired (valid ~5 minutes), already redeemed (auth codes are single-use), or issued for a different appId; clock skew can also invalidate codes.

Common situations: Replaying the callback URL (refresh or retry after an error) after the code was already consumed; delays between callback and token exchange exceeding 5 minutes; redirect URI mismatch between authorize and token calls.

Related errors


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