ExportXMLWordPrintable

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Minor
    • Component/s: github-oauth-plugin
    • None
    • Environment:

      Symptom

      Users authenticate to the UI through GitHub normally. Any client using a Jenkins API token (REST, CLI, mcp-server plugin) works for 8 hours after that UI login, then every request fails with AccessDeniedException3: <user> is missing the Overall/Read permission. The UI session itself keeps working. The failures stop the moment the user loads any UI page, which re-runs the OAuth flow, and start again 8 hours later. With matrix authorization driven by org and team groups this looks to users like a random, daily permission outage. The only server-side trace is an INFO log from GithubAuthenticationToken#loadMyself with GitHub's 401 Bad credentials body, and it does not include the username.

      Root cause

      GithubSecurityRealm.getAccessToken splits GitHub's token response and returns only access_token, discarding refresh_token and expires_in. The access token is stored via GithubSecretStorage and reused by loadUserByUsername2 for every API-token request. Once GitHub expires it, loadMyself gets 401, caches UNKNOWN_TOKEN for one minute, and the constructor throws UsernameNotFoundException("Token not valid"). loadUserByUsername2 then throws UserMayOrMayNotExistException2, and because the realm deliberately does not fire SecurityListener.loggedIn (PR #87, JENKINS-47113), core has no LastGrantedAuthoritiesProperty to fall back to and grants authenticated only. The plugin has no code path that could use a refresh token.

      Steps to reproduce

      1. Create a GitHub App, leave "User-to-server token expiration" enabled, configure its client ID and secret in the GitHub security realm, grant Overall/Read to an org group only.
      2. Log in through the UI, create an API token, confirm curl -u user:token .../whoAmI/api/json shows the org authorities.
      3. Wait 8 hours without loading a UI page. The same curl now returns 403 "missing the Overall/Read permission" and the controller logs loadMyself: Bad credentials.
      4. Load any UI page. The curl works again.

      Workaround

      Opt out of "User-to-server token expiration" on the GitHub App (Optional features). New tokens then behave like classic OAuth App tokens, which is what the plugin was designed around.

      Suggested fixes, either of which would help

      1. Store refresh_token and expires_in alongside the access token and refresh before expiry, with a per-user lock, since using a refresh token invalidates both old tokens and concurrent API-token requests are normal.
      2. Failing that, detect GitHub App client IDs (Iv1. and Iv23 prefixes) and surface an administrative monitor or documentation note that expiring user tokens are not supported.

      Related

      JENKINS-74925 shows the identical loadMyself 401 log from a GitHub App setup. JENKINS-66292 describes sessions dying "under 8hr". https://github.com/jenkinsci/github-oauth-plugin/pull/87 contains the discussion that disabled the loggedIn event.

            Assignee:
            Unassigned
            Reporter:
            Bryan
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: