Unable to generate valid JWT using Bash example
Code of Conduct
- [X] I have read and agree to the GitHub Docs project's Code of Conduct
What article on docs.github.com is affected?
https://docs.github.com/en/[email protected]/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app#example-using-bash-to-generate-a-jwt
What part(s) of the article would you like to see updated?
The Bash example for generating a JWT does not seem to work.
I'm working with a GitHub Enterprise server version 3.10.12.
Current behavior
Using some censored values here, but to illustrate what the current behavior is when I run it:
$ ./generate-jwt.sh Iv1.c0ffeec0ffeec0ff ./my-app.2024-06-03.private-key.pem
JWT: ewogICAgInR5cCI6IkpXVCIsCiAgICAiYWxnIjoiUlMyNTYiCn0.ewogICAgImlhdCI6MTcxNzUwMTk2MCwKICAgICJleHAiOjE3MTc1MDI2MjAsCiAgICAiaXNzIjpJdjEuYzBmZmVlYzBmZmVlYzBmZgp9.YoShUxrZ-fIwyKm6nXrgluU6jXnElLjijQTvUZOk9eeHb5prP64oAJvFYr7ZCNwHYHRGJnrSLNyw2c8LmAo6IGg9bdi_mrE5qzMZO1ZWLqJP6EMqJ1TCvgPS4zHk8dH6GB5JTp_QJsp6n5Q8Kgloqb-oqSbqxt87Sn1nkxyVsVFiZ_8r-wHemCg1mTEub1Vyz3PZHxfrdh_x-r6YwQ8qD8m-uWhBovZLsNDfIxcVhLtSu6msAPiF3oB4_DhcvSuZaROhHGs7umHMWnLP6sWp0unfy_LUFkEPoWx7pDaU--9yqA75cdxDps7LMDehmg1VESc8llvBtsrVQP-8b-gzqw
$ curl -L -H 'Accept: application/vnd.github+json' -H "Authorization: Bearer ${JWT:?}" -H 'X-GitHub-Api-Version: 2022-11-28' 'https://github.example.com/api/v3/app'
{
"message": "A JSON web token could not be decoded",
"documentation_url": "https://docs.github.com/[email protected]/rest"
}
Some notes
One thing that immediately sticks out to me is that the JWT does not start with eyJ0 like I'm used to seeing, but instead ewog. Turns out that's because the script keeps some newlines in the JSON:
$ echo -n '{"typ":"JWT","alg":"RS256"}' | base64
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9
$ echo -en '{\n "typ":"JWT",\n "alg":"RS256"\n}' | base64
ewogICAgInR5cCI6IkpXVCIsCiAgICAiYWxnIjoiUlMyNTYiCn0=
I'm not sure if that is legal. Maybe it is.
Additional information
If we can change the script to output eyJhbGci[…] instead of JWT: eyJhbGci[…], I think that would be very useful. Makes it much easier to use that in a script when a JWT is required.
There are also some warnings from ShellCheck that we may want to fix while we're at it:
$ shellcheck generate-jwt.sh
In generate-jwt.sh line 7:
pem=$( cat $2 ) # file path of the private key as second argument
^-- SC2086 (info): Double quote to prevent globbing and word splitting.
Did you mean:
pem=$( cat "$2" ) # file path of the private key as second argument
In generate-jwt.sh line 10:
iat=$((${now} - 60)) # Issues 60 seconds in the past
^----^ SC2004 (style): $/${} is unnecessary on arithmetic variables.
In generate-jwt.sh line 11:
exp=$((${now} + 600)) # Expires 10 minutes in the future
^----^ SC2004 (style): $/${} is unnecessary on arithmetic variables.
For more information:
https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
https://www.shellcheck.net/wiki/SC2004 -- $/${} is unnecessary on arithmeti...
Thanks for opening this issue. A GitHub docs team member should be by to give feedback soon. In the meantime, please check out the contributing guidelines.
@lindhe Thanks so much for opening an issue! I'll get this triaged for review ✨
Thanks for this issue! You or anyone else is welcome to open a PR to fix/improve this example.
Thanks for saying. I tried fixing it, but couldn't figure it out. Do you have a spec for the JWT, like which fields are required and what to include in the hash?
I have used APP ID instead of CLIENT ID with the script. It then worked for me.
Refs: https://gist.github.com/carestad/bed9cb8140d28fe05e67e15f667d98ad
Is this correct approach? Please advise.
I believe that may be different for different versions of GitHub Enterprise. In Enterprise Cloud they seem to use client_id in the script, while in Enterprise Server 3.10 they seem to use app_id.
Thank you @lindhe for raising this issue, and for providing such helpful info to diagnose the problem! 🙌
When I wrote this script initially, I don't recall there being any issues with JSON decoding. However, I was able to reproduce your error quite easily. After some additional testing, the culprit revealed itself: the variables in the payload JSON were missing an extra set of quotes. Now you'll see the "eyJ0..." you're accustomed to seeing at the top of the token.
I've made a few adjustments to the script--see PR #34134--and all should be working seamlessly. Furthermore, I agree that the "JWT: " included in the print line is unnecessary, and may lead to conflicts for certain users.