Skip to content

fix: cast gh_app_id to string for JWT encoding compatibility#705

Open
jmeridth wants to merge 2 commits intomainfrom
fix/gh-app-id-string-cast
Open

fix: cast gh_app_id to string for JWT encoding compatibility#705
jmeridth wants to merge 2 commits intomainfrom
fix/gh-app-id-string-cast

Conversation

@jmeridth
Copy link
Collaborator

What

Cast gh_app_id to str() when passing it to login_as_app_installation, which internally calls jwt.encode expecting the iss claim to be a string. Updated tests to pass integer app IDs and assert the string conversion occurs.

Why

Since v2.0.0, GitHub App authentication fails with "TypeError: Issuer (iss) must be a string" because newer versions of PyJWT enforce that the iss claim is a string, but gh_app_id was being passed as an integer.

Notes

  • Tests now use assert_called_once_with instead of assert_called_once to verify the exact arguments, preventing this class of regression
  • Test inputs changed from strings to integers to mirror real-world usage where env vars are parsed as ints
  • Relates to GitHub App auth broken since v2.0.0 evergreen#508

Relates to github-community-projects/evergreen#508

## What

Cast gh_app_id to str() when passing it to login_as_app_installation,
which internally calls jwt.encode expecting the iss claim to be a string.
Updated tests to pass integer app IDs and assert the string conversion
occurs.

## Why

Since v2.0.0, GitHub App authentication fails with
"TypeError: Issuer (iss) must be a string" because newer versions of
PyJWT enforce that the iss claim is a string, but gh_app_id was being
passed as an integer.

## Notes

- Tests now use assert_called_once_with instead of assert_called_once to verify the exact arguments, preventing this class of regression
- Test inputs changed from strings to integers to mirror real-world usage where env vars are parsed as ints

Signed-off-by: jmeridth <jmeridth@gmail.com>
@jmeridth jmeridth requested a review from zkoppert as a code owner March 18, 2026 23:52
Copilot AI review requested due to automatic review settings March 18, 2026 23:52
@github-actions github-actions bot added the fix label Mar 18, 2026
@jmeridth jmeridth self-assigned this Mar 18, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes GitHub App authentication failures caused by PyJWT requiring the JWT iss claim to be a string, by ensuring the GitHub App ID is passed as a string when authenticating.

Changes:

  • Cast gh_app_id to str when calling login_as_app_installation.
  • Tighten unit tests to assert exact call arguments and use integer app IDs as inputs.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
auth.py Casts gh_app_id to str in the login_as_app_installation call to satisfy PyJWT issuer requirements.
test_auth.py Updates tests to pass integer app IDs and asserts exact authentication call arguments via assert_called_once_with.

Signed-off-by: jmeridth <jmeridth@gmail.com>
Copy link
Collaborator

@zkoppert zkoppert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter order in test_auth.py lines 87-89 is swapped - b"gh_private_token" is in the gh_app_id position and "gh_app_id" is in the gh_app_private_key_bytes position. I believe it passes because create_jwt_headers is mocked so the wrong types never get exercised.

# Current (incorrect order):
result = get_github_app_installation_token(
    mock_ghe, b"gh_private_token", "gh_app_id", "gh_installation_id"
)

# Should be:
result = get_github_app_installation_token(
    mock_ghe, "gh_app_id", b"gh_private_token", "gh_installation_id"
)

Also, the type annotations for gh_app_id and gh_app_installation_id in get_github_app_installation_token (auth.py line 54) say str, but get_int_env_var("GH_APP_ID") returns int | None in config.py, and issue_metrics.py line 271 passes them as ints. Might want to update these to int to match reality (or keep str and add the str() cast at the call site like you did in auth_to_github).

@zkoppert zkoppert self-requested a review March 19, 2026 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants