justauth/JustAuth · error · AuthException

${error}

Error message

${error}

What it means

AuthException thrown at the very top of AuthAppleRequest.getAccessToken when authCallback.getError() is non-empty. Apple's form_post response includes an error field (plus error_description) when Sign in with Apple fails, and JustAuth surfaces the error string directly as the message.

Source

Thrown at src/main/java/me/zhyd/oauth/request/AuthAppleRequest.java:55

        super(config, AuthDefaultSource.APPLE);
    }

    public AuthAppleRequest(AuthConfig config, AuthStateCache authStateCache) {
        super(config, AuthDefaultSource.APPLE, authStateCache);
    }

    @Override
    public String authorize(String state) {
        return UrlBuilder.fromBaseUrl(super.authorize(state))
            .queryParam("response_mode", "form_post")
            .queryParam("scope", this.getScopes(" ", false, AuthScopeUtils.getDefaultScopes(AuthAppleScope.values())))
            .build();
    }

    @Override
    public AuthToken getAccessToken(AuthCallback authCallback) {
        if (!StringUtils.isEmpty(authCallback.getError())) {
            throw new AuthException(authCallback.getError());
        }
        this.config.setClientSecret(this.getToken());
        // if failed will throw AuthException
        String response = doPostAuthorizationCode(authCallback.getCode());
        JSONObject accessTokenObject = JSONObject.parseObject(response);
        // https://developer.apple.com/documentation/sign_in_with_apple/tokenresponse
        AuthToken.AuthTokenBuilder builder = AuthToken.builder()
            .accessToken(accessTokenObject.getString("access_token"))
            .expireIn(accessTokenObject.getIntValue("expires_in"))
            .refreshToken(accessTokenObject.getString("refresh_token"))
            .tokenType(accessTokenObject.getString("token_type"))
            .idToken(accessTokenObject.getString("id_token"));
        if (!StringUtils.isEmpty(authCallback.getUser())) {
            try {
                AppleUserInfo userInfo = JSONObject.parseObject(authCallback.getUser(), AppleUserInfo.class);
                builder.username(userInfo.getName().getFirstName() + " " + userInfo.getName().getLastName());
            } catch (Exception ignored) {
            }

View on GitHub (pinned to 694bbf1b01)

Solutions

  1. Handle POST on the callback endpoint (Apple posts via form_post) and bind form fields error/error_description/code/user into AuthCallback
  2. If error is user_cancelled_authorize, treat it as a benign cancellation rather than a server fault
  3. Log error_description alongside error for the real reason
  4. Ensure your developer account's Services ID and return URL are configured for Sign in with Apple

Example fix

// before
@PostMapping("/callback/apple")
public Object callback(@RequestParam Map<String,?> params) { ... }

// after — explicitly surface Apple's error before triggering the flow
AuthCallback cb = AuthCallback.of(); // bind error, error_description, code, user from the form POST
if (StringUtils.isNotEmpty(cb.getError())) {
    // user cancelled or Apple rejected — respond 200 with a friendly message
    return redirect("/login?cancelled=true");
}
return authRequest.login(cb);
Defensive patterns

Strategy: validation

Validate before calling

// Apple posts the callback via form_post — read form fields and check error first
AuthCallback cb = AuthCallback.of(); // bind error/error_description/code/user from the POST body
if (StringUtils.isNotEmpty(cb.getError())) {
    boolean cancelled = "user_cancelled_authorize".equals(cb.getError());
    return cancelled ? redirect("/login?cancelled=true") : redirect("/login?error=" + cb.getError());
}

Prevention

When it happens

Trigger: Apple posting back an error such as user_cancelled_authorize, invalid_request, or unauthorized_client in the form body. Because response_mode=form_post (set in authorize()), the callback arrives as an HTTP POST form — a GET handler will see an empty callback and may mishandle it first.

Common situations: User tapped 'Cancel' on the Apple consent sheet; the web auth session expired before completion; the callback endpoint only accepts GET so the POST form fields are never bound to AuthCallback; private-email relay issues causing error_description on return.

Related errors


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