Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot authenticate with token or use "installation" method #184

Closed
chopfitzroy opened this issue Oct 1, 2020 · 13 comments · Fixed by #280
Closed

Cannot authenticate with token or use "installation" method #184

chopfitzroy opened this issue Oct 1, 2020 · 13 comments · Fixed by #280
Projects

Comments

@chopfitzroy
Copy link

chopfitzroy commented Oct 1, 2020

I am trying to do an app installation and have tried two different methods and cannot seem to authenticate with either, although I do get different errors.

I have installed the app (which is in an org I have created) to my account, and using the installation_id that is present in the querystring of the callback URL I am trying to authenticate.

The more basic/manual method I have tried is as follows:

const { readFileSync } = require('fs');

import { createAppAuth } from '@octokit/auth-app';
import { request as githubRequest } from '@octokit/request';

const key = readFileSync(__dirname + '/github_app.pem');

const auth = createAppAuth({
    id: process.env.API_GH_APP_ID,
    privateKey: key,
    // clientId: process.env.API_GH_APP_CLIENT,
    // clientSecret: process.env.API_GH_APP_SECRET,
});

const githubAuthorization = async (request, response) => {
    try {
        const { id: installationId } = request.body;

        if (!installationId) {
            response.status(200).json({ error: `Invalid 'installationId' passed to 'githubAuthorization'` });
            return;
        }

        const { token } = await auth({ type: "app" });

        const result = await githubRequest(`POST https://api.github.com/app/installations/${installationId}/access_tokens`, {
            headers: {
                authorization: "token " + token
            }
        });

        response.status(200).json(result);
        return;

    } catch (err) {
        console.log({ err });
        response.status(200).json(err);
    }

};

export default githubAuthorization;

This throws the following error:

RequestError [HttpError]: A JSON web token could not be decoded at node_modules/@octokit/request/dist-node/index.js:66:23

NOTE that if I console the token it shows a valid string.

The second method I have tried is (inspired by this question):

const { readFileSync } = require('fs');

import { createAppAuth } from '@octokit/auth-app';
import { request as githubRequest } from '@octokit/request';

const key = readFileSync(__dirname + '/github_app.pem');

const auth = createAppAuth({
    id: process.env.API_GH_APP_ID,
    privateKey: key,
    // clientId: process.env.API_GH_APP_CLIENT,
    // clientSecret: process.env.API_GH_APP_SECRET,
});

const githubAuthorization = async (request, response) => {
    try {
        const { id: installationId } = request.body;

        if (!installationId) {
            response.status(200).json({ error: `Invalid 'installationId' passed to 'githubAuthorization'` });
            return;
        }

        const { token } = await auth({ type: "installation", installationId });

        const result = await githubRequest("GET /orgs/:org/repos", {
            headers: {
                authorization: "token " + token
            },
            org: "orgname",
            type: "public"
        });

        response.status(200).json(result);
        return;
    } catch (err) {
        console.log({ err });
        response.status(200).json(err);
    }

};

export default githubAuthorization;

However this gives the following error:

RequestError [HttpError]: Missing 'issuer' claim ('iss') in assertion at node_modules/@octokit/request/dist-node/index.js:66:23

NOTE if I try to console token here I get nothing meaning it is bailing on await auth({ type: "installation", installationId });

I have tried to stick to the documentation samples as much as possible but I am struggling to see what to do from this point onwards.

@ghost ghost added this to Inbox in JS Oct 1, 2020
@gr2m gr2m added the support label Oct 1, 2020
@gr2m gr2m self-assigned this Oct 1, 2020
@ghost ghost moved this from Inbox to Support in JS Oct 1, 2020
@ghost ghost moved this from Support to In progress in JS Oct 1, 2020
@gr2m
Copy link
Contributor

gr2m commented Oct 1, 2020

Hi @chopfitzroy, I tried to reproduce the problems you created. I found one bug in your code, after fixing that it all works as expected. You need to change the authorization header prefix from token to bearer when authenticating with a JWT

See my code at
https://runkit.com/gr2m/octokit-auth-app-js-184/1.0.0

What is it exactly that you are trying to accomplish? The first code example is unnecessary complex, you don't need to send a manual request to create an installation access token, just use auth({ type: 'installation', installationId }) instead.

@chopfitzroy
Copy link
Author

Hey @gr2m,

The first example was just experimentation when the second example did not work.

Using test2 I was able to list the repositories, but when I swapped out my own, id, privateKey (did this inline just to make sure), installationId and org I got the same error as before?

(node:2173) UnhandledPromiseRejectionWarning: HttpError: Missing 'issuer' claim ('iss') in assertion
    at node_modules/@octokit/request/dist-node/index.js:66:23
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async getInstallationAuthentication (node_modules/@octokit/auth-app/dist-node/index.js:161:7)
(node:2173) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

Based on this I would assume I have configured something wrong, I can see the app is installed in the install app menu:

image

and:

image

Any ideas? Sorry for the info dump just trying to get everything that could be relevant down.

@gr2m
Copy link
Contributor

gr2m commented Oct 1, 2020

I'm afraid I haven't seen this error before :(

Does this work?

        const { token } = await auth({ type: "app" });
        console.log(token)
        const result = await githubRequest(`POST https://api.github.com/app/installations/${installationId}/access_tokens`, {
            headers: {
                authorization: "bearer " + token
            }
        });

If not, can you paste the token here and see what you get as payload? https://www.jsonwebtoken.io/ It should look like this

{
 "iat": 1601591683,
 "exp": 1601599068,
 "iss": 83211,
 "jti": "814d33f1-9edf-4e00-8bd3-4843c6709629"
}

If it does, can you try to reproduce the error by sending a curl request? If it doesn't, can you please contact support: support.github.com/contact, they will be able to help you further, I'm afraid I'm out of ideas on what I can do to help on the client side

@chopfitzroy
Copy link
Author

Using the above code, same error, the token is logged as follows:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MDE1OTYzNzIsImV4cCI6MTYwMTU5Njk3MiwiaXNzIjpudWxsfQ.nOdid2PQfobmfaQE0aibPW0C-RPr3e14sbpe7ixYy2LnPT0f7-o-phAO5pFdzf9CZH4i7Kh0U2pqWo-OheY-y5L7SqFcErREvRY1a4y0ChZEWGgJiwZbkv6MvlNC-dIMAauU97AvcwgadhwRSHeB3aMkpZR4XUwopbSkuWww9iaSunRZKF6uvoY6FCuBwNjqKSIjjAuRvfKj3DuFeWjDhIhjqRbxjnhOlsVJjv236xjhCXl1-V-ajQsM7YwY0o1lsj2XafvS8F6eBEq0D8ll4yEoorLUQSPs2GhWFqRsB_QKRutmkGVXNr2YPgmWFKeDcvmsxKMrQP7QRNDIk9O-Fg
{
  err: RequestError [HttpError]: Missing 'issuer' claim ('iss') in assertion
      at node_modules/@octokit/request/dist-node/index.js:66:23

Looks like it verifies correctly:

image

Except the iss field is null which would explain the error, not sure what this means.

@gr2m
Copy link
Contributor

gr2m commented Oct 1, 2020

me neither, I suggest you contact support. Please keep me posted and reference this issue, I'm happy to help the great support folks in any way I can, they know how to reach me

@chopfitzroy
Copy link
Author

chopfitzroy commented Oct 1, 2020

Hey @gr2m fantastic will move this to support, thank you so much for all your help debugging this 😁

NOTE putting here for reference, ticket logged with support: 854622.

@chopfitzroy
Copy link
Author

Hey @gr2m I figured it out, and it is really embarrassing.

This line in all of my examples was the only thing I did not try swapping out for a "hard coded" string:

id: process.env.API_GH_APP_ID,

Well through another issue I discovered that my environment variables were not being populated, once I resolved this issue and re-tried everything went through first try! I am so sorry for taking up so much of your time!

One thing I have learnt from this, is would it be worth adding some sort of null / undefined checker to octokit to say that no id has been provided? Realize this is a bit of an "off chance" bug, but thought I would voice it incase.

@gr2m
Copy link
Contributor

gr2m commented Oct 5, 2020

One thing I have learnt from this, is would it be worth adding some sort of null / undefined checker to octokit to say that no id has been provided? Realize this is a bit of an "off chance" bug, but thought I would voice it incase.

I agree. Would you like to get a pull request going? You can start with just a failing test and we can continue the discussion there?

@ghost ghost moved this from In progress to Awaiting response in JS Oct 14, 2020
@gr2m gr2m removed their assignment Oct 14, 2020
@chopfitzroy
Copy link
Author

Get @gr2m yes absolutely, I will try to get onto this this weekend.

@gr2m
Copy link
Contributor

gr2m commented Oct 21, 2020

would you still like to work on it?

I think @octokit/auth-app should throw a meaningful error if it's attempting to create an installation access token without the installationId being set in either the strategy options or the .auth() options. If you are busy I can look into it myself, I see people repeatedly running into this problem, a helpful error message will help greatly to help folks help themselves

@gr2m gr2m closed this as completed in #280 Apr 22, 2021
JS automation moved this from Awaiting response to Done Apr 22, 2021
@github-actions
Copy link
Contributor

🎉 This issue has been resolved in version 3.4.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@scarlac
Copy link

scarlac commented Feb 28, 2023

For any lost souls coming from Google, the error Missing 'issuer' claim ('iss') may also be caused by a wrong app_id: value. In my case it was because I had incorrectly used the Client ID (e.g. Iv7.1abcdefg01234567) instead of the App ID (e.g. 42) as the app_id: ... value when configuring the actions/github-app-token action with: parameters.
ie. this is wrong:

- name: Get token
  uses: actions/github-app-token@v1
  with:
    app_id: Iv7.1abcdefg01234567
    private_key: ${{ secrets.SHH }}

And this would be right:

- name: Get token
  uses: actions/github-app-token@v1
  with:
    app_id: 42
    private_key: ${{ secrets.SHH }}

@siddheshranade
Copy link

@gr2m 4 years late but after spending hours trying to make a POST request using GitHub API your first comment above finally solved my issue, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
JS
  
Done
Development

Successfully merging a pull request may close this issue.

4 participants