Help
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Copilot Lvl 2
Message 1 of 4

Using JWT to get user info

Hi!

I wrote a script in Ruby to make 3 curl requests. In the first two requests I am asking for GitHub user information using the endpoint https://api.github.com/users/username, the first without a JWT in the header, and the second without a JWT in the header.

 

 

# Generate the JWT
payload = { 
  # The time that this JWT was issued, _i.e._ now.
  iat: Time.now.to_i,

  # JWT expiration time (10 minute maximum)
  exp: Time.now.to_i + (10 * 60),

  # Your GitHub App's identifier number
  iss: APP_IDENTIFIER
}
# Cryptographically sign the JWT.
jwt = JWT.encode(payload, PRIVATE_KEY, 'RS256')

puts "Don't use JWT to get user info"
puts `curl -i -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/users/octocat`

puts "Use JWT to get user info"
puts `curl -i -H "Authorization: Bearer #{jwt}" -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/users/octocat`

puts "Show plans active on my GitHub account"
puts `curl -i -H "Authorization: Bearer #{jwt}" -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/marketplace_listing/accounts/123456`

 

From what I understand, this user info endpoint does not require authentication. But, I would like to be authenticated as an app so that I can have API rate limit.

 

For some reason, when I run this script, the 2nd curl (asking for user info with the jwt in the header) fails. The first curl (with no JWT in the header) succeeds though. I know that I did not insert the jwt incorrectly because the third curl, which uses the same JWT, succeeds.

 

This is what I get from the 2nd curl:

HTTP/1.1 401 Unauthorized
Date: Tue, 13 Aug 2019 23:15:05 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 93
Server: GitHub.com
Status: 401 Unauthorized
X-GitHub-Media-Type: github.machine-man-preview; format=json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 35
X-RateLimit-Reset: 1565740916
Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
X-GitHub-Request-Id: 8782:4DF8:4E2B0:5E58C:5D534479

{
  "message": "Bad credentials",
  "documentation_url": "https://developer.github.com/v3"
}

Can someone explain why I'm getting bad credentials error?

Thanks.

 

3 Replies
Community Manager
Message 2 of 4

Re: Using JWT to get user info

Have you tried using the exact code that is offered in the documentation? Your sample code leaves out how `PRIVATE_KEY` is initialized, so it's hard to say what might be going wrong if we can't see all the code.

 

Also, you don't need to be authenticated as an app to have an API rate limit. All connections to our API are rate limited in one way or another.

 

Let us know if you can supply more information.

Copilot Lvl 2
Message 3 of 4

Re: Using JWT to get user info

Hi, I've tried using the the exact code shown in the documentation, albeit from a different source.

I used the initialized PRIVATE_KEY by loading it from .env file.

 

Ah what I meant by the API limits is that I wanted to use the higher rates.

 

The complete script is here:

require 'openssl'
require 'dotenv/load'
require 'jwt'  # https://rubygems.org/gems/jwt

# Converts the newlines. Expects that the private key has been set as an
# environment variable in PEM format.
PRIVATE_KEY = OpenSSL::PKey::RSA.new(ENV['GITHUB_PRIVATE_KEY'].gsub('\n', "\n"))

# The GitHub App's identifier (type integer) set when registering an app.
APP_IDENTIFIER = ENV['GITHUB_APP_IDENTIFIER']


# Generate the JWT
payload = { 
  # The time that this JWT was issued, _i.e._ now.
  iat: Time.now.to_i,

  # JWT expiration time (10 minute maximum)
  exp: Time.now.to_i + (10 * 60),

  # Your GitHub App's identifier number
  iss: APP_IDENTIFIER
}
# Cryptographically sign the JWT.
jwt = JWT.encode(payload, PRIVATE_KEY, 'RS256')

puts "Don't use JWT to get user info"
puts `curl -i -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/users/octocat`

puts "Use JWT to get user info"
puts `curl -i -H "Authorization: Bearer #{jwt}" -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/users/octocat`


puts "Show plans active on a GitHub account"
puts `curl -i -H "Authorization: Bearer #{jwt}" -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/marketplace_listing/accounts/123456`

I do not think there is anything wrong with how I initialized the JWT, because I successfully authenticated using the JWT in the 3rd curl (I successfully receieved the expected information and saw that I had a limit of 5000, as opposed to the 60 limit I had without authentication).

Community Manager
Message 4 of 4

Re: Using JWT to get user info

I suspect what might be going on here is that your GitHub App has the `Plan` permission on it? If so, the documentation for the Get a single user endpoint states that it has to be authenticated as a user in order to access that information. I don't see any alternative there other than connecting in an unauthenticated manner.

 

Is my understanding correct?