justauth/JustAuth · error · AuthException

object.getString("error_description")

Error message

object.getString("error_description")

What it means

AuthLinkedinRequest.checkResponse throws AuthException(source=linkedin) with 'error_description' when the LinkedIn API response contains an 'error' key. This is LinkedIn's standard OAuth2 error body (invalid_grant, invalid_client, expired token, etc.).

Source

Thrown at src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java:168

    }

    private String getUserName(JSONObject userInfoObject, String nameKey) {
        String firstName;
        JSONObject firstNameObj = userInfoObject.getJSONObject(nameKey);
        JSONObject localizedObj = firstNameObj.getJSONObject("localized");
        JSONObject preferredLocaleObj = firstNameObj.getJSONObject("preferredLocale");
        firstName = localizedObj.getString(preferredLocaleObj.getString("language") + "_" + preferredLocaleObj.getString("country"));
        return firstName;
    }

    /**
     * 检查响应内容是否正确
     *
     * @param object 请求响应内容
     */
    private void checkResponse(JSONObject object) {
        if (object.containsKey("error")) {
            throw new AuthException(object.getString("error_description"), source);
        }
    }

    /**
     * 获取token,适用于获取access_token和刷新token
     *
     * @param accessTokenUrl 实际请求token的地址
     * @return token对象
     */
    private AuthToken getToken(String accessTokenUrl) {
        HttpHeader httpHeader = new HttpHeader();
        httpHeader.add("Host", "www.linkedin.com");
        httpHeader.add(Constants.CONTENT_TYPE, "application/x-www-form-urlencoded");

        String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl, null, httpHeader).getBody();
        JSONObject accessTokenObject = JSONObject.parseObject(response);

        this.checkResponse(accessTokenObject);

View on GitHub (pinned to 694bbf1b01)

Solutions

  1. Read error_description: 'we've made some changes...' style messages mean scope/endpoint migration is required (use r_liteprofile or OpenID Connect)
  2. Match redirectUri exactly (scheme, host, path, trailing slash) with the LinkedIn app's OAuth 2.0 settings
  3. Ensure the authorization code is exchanged within 30 seconds of issuance and only once
  4. For restricted apps, request review of the member permissions before going live

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
    linkedinRequest.getAuthResponse(callback);
} catch (AuthException e) {
    // error_description names the OAuth2 failure
    if (e.getMessage() != null && e.getMessage().contains("expired")) {
        return redirectToAuthorize();
    }
    throw e;
}

Prevention

When it happens

Trigger: Token exchange, refresh, or GET /v2/me when LinkedIn returns {"error":"...","error_description":"..."} — e.g. the 2019 API migration where old r_basicprofile scopes and v1 endpoints were retired.

Common situations: Using legacy scopes (r_basicprofile) instead of r_liteprofile/openid, expired or already-consumed auth code, wrong redirect URI not matching the LinkedIn app config, or an unapproved app requesting member permissions.

Related errors


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