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
- Never exchange the same auth_code twice — if the first exchange may have succeeded, persist the token instead of retrying the exchange
- Process the callback immediately; Alipay auth codes expire in about 5 minutes
- Ensure the appId/redirectUri used at authorize time matches the one at token-exchange time
- 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
- Exchange the auth_code exactly once, immediately upon callback
- Persist the token atomically right after a successful exchange so retries never re-exchange
- Queue webhook callbacks if processing may delay past the 5-minute window
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.