Invalid credentials when get an access token


I followed the instruction

  1. Created new GitHub App and stored app_id from WebUI

  2. Installed my GitHub App to my git account and stored installation_id from WebUI

  3. Dowloaded the private key file, performed a JWT token and encode it by RS256. Payload of JWT is

    var payload = new
    iat = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds,
    exp = (int)(DateTime.UtcNow.AddMinutes(9) - new DateTime(1970, 1, 1)).TotalSeconds,
    iss = {app_id}

But when I POST to url{installation_id}/access_tokens with headers:

Accept: application/vnd.github.machine-man-preview+json
Authorization: Bearer {JWT}
User-Agent: TestApp

But I got the message:

{“message”:“Invalid credentials”,“documentation_url”:“”}

I guess that my JWT is correct because if I test with non-exist iss (for example 111111111) I get

Integration not found

as well as if I use wrong exp (for example, more 10 min) I also get another error

Expiration time’ claim (‘exp’) is too far in the future.

But I don’t know what I do wrong. Please help. Thanks.


Hey @hypercodeplace :wave:

As far as I can tell, the “Invalid credentials” message indicates one of several possible problems with decoding and validating a JWT. Can you try decoding the token you created using a tool you didn’t build yourself (e.g. some of the online or command line tools available out there) and see if that works and if it can give more information about what’s wrong?

As an alternative, can you provide a complete example for reproducing this problem using command line tools (both for creating a JWT and for making the API call, e.g. curl)? That should help us offer advice.

I’ll also ask the team if it’d be possible to catch more specific problems on our end and provide more helpful error messages for those problems, but can’t make any promises.


Hi @izuzak.

Thank you for your reply.

I tried to decode my jwt by and and it works fine. For both services I get the same information that was encoded before.

I created the demo console application and share it

Thank you for your help!


I created the demo console application and share it

@hypercodeplace Thanks, but could you please reproduce the problem using command line tools like curl, as I mentioned before? We don’t run and debug code like that (covering all the various frameworks out there). For example, I don’t have .NET installed myself.


@izuzak I can reproduce by curl only sending data to GitHub like this:

curl -i -X POST \
-H "Authorization: Bearer $JWT" \
-H "Accept: application/vnd.github.machine-man-preview+json" \

But I don’t know how I can generate JWT by curl. Is there some way to do it by console tool?


But I don’t know how I can generate JWT by curl.

@hypercodeplace I’m pretty sure that’s not possible since curl is a tool for making HTTP requests. I was suggesting you use curl to demonstrate the second step of the process that’s causing you trouble (step 1 is creating the token). Also, I didn’t ask for the curl command itself, but for the full output of running that command with the -v flag (with only sensitive information masked).

Is there some way to do it by console tool?

I’d be surprised if there’s no easy-to-install command line tool which can do this. But I haven’t searched for such tools myself, so I can’t offer a recommendation.

As an alternative, can you reproduce the problem in Ruby, using this library: ? If you can, share a full example for that and I’ll try to take a look at that.

The example in the documentation uses Ruby, so you can re-use that:


Hey @hypercodeplace :wave:

Just wanted to let you know that the team made some changes so that the endpoint for creating a token returns more helpful error messages for invalid JWTs. If you give this another try – we’d be curious to hear if you get something different back now or still the same “invalid credentials” error.

Thanks again!


Hi, @izuzak
I found a solution for C#. I use BouncyCastle and Jose libs to create token from PEM file. This is the code:

using System.IO;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;

public static class JWT
    public static string CreateToken(object payload, string pemKeyFileName)
        var keyPair = GetKeyPair(pemKeyFileName);
        var rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyPair.Private);

        using (var rsa = new RSACryptoServiceProvider())
            return Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);

    private static AsymmetricCipherKeyPair GetKeyPair(string pemKeyFileName)
        using (var sr = new StreamReader(pemKeyFileName))
            var pr = new PemReader(sr);
            return (AsymmetricCipherKeyPair)pr.ReadObject();

Thank you for your help.