Coder Social home page Coder Social logo

auth-app.js's People

Contributors

copperwall avatar dependabot[bot] avatar dscho avatar frangio avatar github-actions[bot] avatar gr2m avatar greenkeeper[bot] avatar hmedney avatar joekrill avatar jsoref avatar kammerjaeger avatar kfcampbell avatar lencioni avatar mause avatar nicholasjpaterno avatar nickfloyd avatar nickliffen avatar nitrocode avatar octokitbot avatar oscard0m avatar renovate[bot] avatar romanbalayan avatar steve-norman-rft avatar suhaibmujahid avatar wolfy1339 avatar ysato avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

auth-app.js's Issues

Best Practise Proxy Support πŸ˜€πŸ‘πŸΌ

Hey πŸ‘‹πŸ»,

I have a question, we are looking to use this module alongside the @octokit/graphql.js.

We work behind a corporate proxy, so we need to be able to pass a proxy to any egress request from within our network.

I see that both this and the @octokit/graphql.js modules use the @octokit/request.js) module to make its requests to the GitHub API.

By taking a look at your code, you seem to be using node-fetch for actually making the HTTP Requests behind the scenes.

Taking a look at node-fetch it does support passing in an agent. When taking a look at your request library, there doesn't seem to be any options, which I would have expected to see here? (maybe?)

We would love to be able to pass in a httpsAgent somewhere?

const { createAppAuth } = require("@octokit/auth-app");
const httpAgent = new http.Agent({ keepAlive: true });
const httpsAgent = new https.Agent({ keepAlive: true });

const auth = createAppAuth({
  id: 1,
  privateKey: "-----BEGIN PRIVATE KEY-----\n...",
  installationId: 123,
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef12341234567890abcdef1234"
});

const installationAuthentication = await auth({ 
  type: "installation" ,
  agent: url => url.protocol === 'https:' ? httpsAgent : httpAgent
});

const graphqlWithAuth = graphql.defaults({
  request: {
    hook: auth.hook
    agent: url => url.protocol === 'https:' ? httpsAgent : httpAgent
  }
});

Something like that? It would be great if we could do this in a single place when looking through the octokit modules, it would be great to have a single experience across the @octokit ecosystem πŸ€”?

Just wanted to put it here and get some of your thoughts on best practice πŸ‘

Thanks for all your help.

TS: having to cast to specific Authentication types since 3.3.0

FYI, with the latest released version, I'm needing to cast to the specific type of authentication result now, where before it felt more like a type union... not sure if this is a surprise or not, but wanted to make you aware.

Updated code to build with 3.3.0:

const installationTokenDetails = await installationAppAuth({ type: 'installation' });
const installationToken = (installationTokenDetails as InstallationAccessTokenAuthentication).token;

Before:

const installationTokenDetails = await installationAppAuth({ type: 'installation' });
const installationToken = installationTokenDetails.token;

An in-range update of prettier is breaking the build 🚨

The devDependency prettier was updated from 1.18.2 to 1.19.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

prettier is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details

Release Notes for Prettier 1.19: Long awaited Vue option, TypeScript 3.7 and new JavaScript features

diff

πŸ”— Release Notes

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of @types/jsonwebtoken is breaking the build 🚨

The dependency @types/jsonwebtoken was updated from 8.3.2 to 8.3.3.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/jsonwebtoken is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Question: Auto refreshing installation tokens

We are running long lived background deamons and seeing some 401 errors when using installation tokens. My/our expectation was that tokens are cached (we can see this happening correctly) and refreshed automatically after they expire.

Is this correct? Or do we need to take explicit actions to handle 401 Bad Credentials errors and refresh any tokens?

Tnx!

Handle 401 response when using installation token shortly after creation

This is a follow up to octokit/plugin-paginate-rest.js#33

Here is a simplified test case that I run in GitHub Actions.

(async () => {
  for (let index = 0; index < 10000; index++) {
    try {
      const { Octokit } = require("@octokit/core");
      const { createAppAuth } = require("@octokit/auth-app");

      const octokit = new Octokit({
        authStrategy: createAppAuth,
        auth: {
          id: process.env.TEST_APP_ID,
          privateKey: process.env.TEST_APP_PRIVATE_KEY,
          installationId: process.env.TEST_APP_INSTALLATION_ID,
        },
      });

      await octokit.request("GET /installation/repositories", {
        mediaType: {
          previews: ["machine-man"],
        },
      });

      process.stdout.write(".");
    } catch (error) {
      console.log("Error: ", error);
      process.exit(1);
    }
  }

  console.log("");
})();

Here is a run that triggered the expected error:
https://github.com/octokit/sandbox/runs/705154995?check_suite_focus=true#step:5:1

The way this could work

  1. Keep track on weather any request was successful
  2. If the first request using the installation authentication token fails with 401, log a warning and retry after 1s, then 2s, then 4s. The warning should include an explanation why the delay might be necessary in some cases
  3. If a previous request using the same access token was successful, do not retry in case of a 401

I have asked the documentation team to document that behavior so we can reference it from our docs and error messages

/cc @steve-norman-rft @droidpl

An in-range update of fetch-mock is breaking the build 🚨


☝️ Important announcement: Greenkeeper will be saying goodbye πŸ‘‹ and passing the torch to Snyk on June 3rd, 2020! Find out how to migrate to Snyk and more at greenkeeper.io


The devDependency fetch-mock was updated from 9.3.0 to 9.3.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

fetch-mock is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ test (12): There are 2 failures, 0 warnings, and 0 notices.
  • ❌ test (10): There are 2 failures, 0 warnings, and 0 notices.
  • ❌ test (8): There are 1 failures, 0 warnings, and 0 notices.

Commits

The new version differs by 7 commits.

  • d22e983 linked to cheatsheet EVERYWHERE
  • 1d2557d Merge pull request #524 from wheresrhys/cheatsheet
  • 1dfc6c2 completed cheatsheet
  • 7efa6c5 cheatsheet formatting
  • 438c835 refined set up/teardown section of cheatsheet
  • 6a2d449 midway through writing cheatsheet content
  • 633cf3e improve documentation for when to use a named matcher

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of prettier is breaking the build 🚨


☝️ Important announcement: Greenkeeper will be saying goodbye πŸ‘‹ and passing the torch to Snyk on June 3rd, 2020! Find out how to migrate to Snyk and more at greenkeeper.io


The devDependency prettier was updated from 2.0.2 to 2.0.3.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

prettier is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ test (13): There are 2 failures, 0 warnings, and 0 notices.
  • ❌ test (12): There are 1 failures, 0 warnings, and 0 notices.
  • ❌ test (10): There are 2 failures, 0 warnings, and 0 notices.
  • βœ… update_prettier: There are 0 failures, 1 warnings, and 0 notices.

Release Notes for 2.0.3

πŸ”— Changelog

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Cannot authenticate with token or use "installation" method

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.

An in-range update of @octokit/types is breaking the build 🚨


☝️ Important announcement: Greenkeeper will be saying goodbye πŸ‘‹ and passing the torch to Snyk on June 3rd, 2020! Find out how to migrate to Snyk and more at greenkeeper.io


The dependency @octokit/types was updated from 2.7.1 to 2.8.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@octokit/types is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • ❌ test (13): There are 1 failures, 0 warnings, and 0 notices.
  • ❌ test (12): There are 2 failures, 0 warnings, and 0 notices.
  • ❌ test (10): There are 2 failures, 0 warnings, and 0 notices.

Release Notes for v2.8.0

Features

  • endpoint response types
  • GetResponseTypeFromEndpointMethod and GetResponseDataTypeFromEndpointMethod helpers
Commits

The new version differs by 1 commits.

  • cc94eab feat: endpoint response types, GetResponseTypeFromEndpointMethod and GetResponseDataTypeFromEndpointMethod helpers (#34)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Make compatible with browsers

In theory, apps could run entirely in "browsers", including receiving webhooks by utilizing https://smee.io/ or a similar service.

The reason that it’s not compatible right now is the jsonwebtoken dependency. It would be worth looking into an alternative that utilizes the SubtleCrypto browser API, and a polyfill for Node

Use @octokit/auth-oauth-app

  • First step would be to deprecate auth({ type: "oauth" }) and replace it with auth({ type: "oauth-user" }) (done via #264)
  • once we use @octokit/auth-oauth-app internally, we can introduce auth({ type: "oauth-app" }) and auth({ type: "oauth-user", factory })

This will also resolve #252

How does the oauth flow work?

Hi,

in order for my GitHub Apps to be installed, I wanted to use the oauth flow.
In most cases, when you initialise an oauth flow, you get an URL, which you send your users to.
So I was wondering where does octokit generate the URL, and how do I get it?

'type: "auth"' not working

I have an Octokit instance setup as shown below:

import { Octokit as HttpClient } from '@octokit/core';
import { createAppAuth } from '@octokit/auth-app';
import { Azure } from './Azure';

export class Octokit {
    public static Client: HttpClient;

    public static async SetClientAsync(): Promise<void> {
	this.Client = new HttpClient({
		authStrategy: createAppAuth,
		auth: {
			id: 72569,
			type: 'app',
			privateKey: await Azure.GetPrivateKeyAsync()
		},
		previews: [
			'machine-man'
		],
		log: {
			debug: console.debug,
			info: console.info,
			warn: console.warn,
			error: console.error
		},
		userAgent: 'Creeper-Bot',
		timeZone: 'America/Sao_Paulo'
	});
    }
}

And I get the following error when trying to make a request:
(node:11452) UnhandledPromiseRejectionWarning: Error: [@octokit/auth-app] installationId option is required for installation authentication.

let response = await Octokit.Client.request('GET /repos/:owner/:repo/assignees/:assignee', {
	owner: owner,
	repo: repo,
	assignee: assignee
});

I've tried following the documentation but there isn't a clear one for app authentication, am I doing something wrong?

πŸ’‘ Dream code to simplify requests for each installation / repository

Example: dispatch event in all repositories of all installations

Simplified version without taking pagination into account.

const octokit = new Octokit({
  auth: {
    id: APP_ID,
    privateKey: PRIVATE_KEY
  },
  authStrategy: createAppAuth
});

const { data: installations } = await octokit.request(
  "GET /app/installations",
  { mediaType: { previews: ["machine-man"] } }
);

for (const { id, account: { login } } of installations) {
  const installationOctokit = new Octokit({
    auth: {
      id: APP_ID,
      privateKey: PRIVATE_KEY,
      installationId: id
    },
    authStrategy: createAppAuth
  });

  const { data: repositories } = await installationOctokit.request(
    "GET /installation/repositories",
    { mediaType: { previews: ["machine-man"] } }
  );

  for (const { name, full_name } of repositories) {
    await installationOctokit.request("POST /repos/:owner/:repo/dispatches", {
      owner: login,
      repo: name,
      event_type: "my_event",
      client_payload: {
        foo: "bar"
      }
    });
    console.log("Event distpatched for %s", full_name);
  }
}

My dreamcode:tm: alternative for the code above would look something like this

const app = new App({
  auth: {
    id: APP_ID,
    privateKey: PRIVATE_KEY
  }
});

for await (const octokit of app.eachInstallation.iterator) {
  const { data: repositories } = await installationOctokit.request(
    "GET /installation/repositories",
    { mediaType: { previews: ["machine-man"] } }
  );

  for (const { name, full_name } of repositories) {
    await installationOctokit.request("POST /repos/:owner/:repo/dispatches", {
      owner: login,
      repo: name,
      event_type: "my_event",
      client_payload: {
        foo: "bar"
      }
    });
    console.log("Event distpatched for %s", full_name);
  }
}

Or even better

const app = new App({
  auth: {
    id: APP_ID,
    privateKey: PRIVATE_KEY
  }
});

for await (const repo of app.eachRepository.iterator()) {
    await repo.createDispatchEvent({
      event_type: "my_event",
      client_payload: {
        foo: "bar"
      }
    });
    console.log("Event distpatched for %s", repo.full_name);
  }
}

Remove "scope" functionality from OAuth APIs

GitHub apps support the OAuth web flow to create authorization tokens for users:
https://docs.github.com/en/developers/apps/identifying-and-authorizing-users-for-github-apps

But these OAuth tokens work differently from the tokens created by OAuth apps.

OAuth Apps do not get installed on repositories with a set of permissions. In order to limit what a user authorization token can do, the OAuth web flow supports the "scope" query parameter for the OAuth web flow.

GitHub Apps on the other side get installed and each installation grants the app a specific set of permissions at this point. When an app creates an OAuth token, the tokens is limited by the permissions and repository access of the respective installation.

So to make it short, all scope functionality for OAuth needs to be removed from this library.

Allow to set default installationId in strategy Options

const auth = createAppAuth({
  id: 1,
  privateKey: "-----BEGIN RSA PRIVATE KEY-----\n...",
  installationId: 123
});

const installationAuthentication = await auth();

This would be the same as

const auth = createAppAuth({
  id: 1,
  privateKey: "-----BEGIN RSA PRIVATE KEY-----\n..."
});

const installationAuthentication = await auth({ installationId: 123 });

App tries to authenticate as installation for Marketplace endpoints

The marketplace routes need to be added to

const PATHS = [
"/app",
"/app/installations",
"/app/installations/:installation_id",
"/app/installations/:installation_id",
"/app/installations/:installation_id/access_tokens",
"/orgs/:org/installation",
"/orgs/:org/installation",
"/repos/:owner/:repo/installation",
"/repos/:owner/:repo/installation",
"/users/:username/installation",
"/users/:username/installation",
];

An in-range update of @octokit/request is breaking the build 🚨

The dependency @octokit/request was updated from 5.2.1 to 5.3.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@octokit/request is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details

Release Notes for v5.3.0

5.3.0 (2019-10-24)

Features

  • better Typescript definitions via @octokit/types (d868a31)
FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Cannot push to the Git repository.

semantic-release cannot push the version tag to the branch master on the remote Git repository with URL https://x-access-token:[secure]@github.com/octokit/auth-app.js.

This can be caused by:


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

Incorrect target url

When trying to auth, it looks like there is a typo in the url path. I am seeing double slashes in the generated url.

'https://[REDACTED]/api/v3/app/installations//access_tokens'

  const { enterpriseServer219Admin } = require('@octokit/plugin-enterprise-server');
  const { createAppAuth } = require('@octokit/auth-app');
  const { Octokit } = require('@octokit/rest');
  const privateKey = process.env.GHE_KEY;
  const OctokitEnterprise219 = Octokit.plugin(enterpriseServer219Admin);

  const octokit = new OctokitEnterprise219({
    authStrategy: createAppAuth,
    auth: {
      id: 13,
      privateKey
    },
    baseUrl: "https://[REDACTED]/api/v3"
  });

  try {
    const data = await octokit.repos.getContents({
      owner: [CODE_OWNER],
      repo: [REPO],
      path: [FILE_PATH]
    });
    console.log(data);
  } catch (error) {
    console.log(error);
  }

The above code returns this:

{
  name: 'HttpError',
  status: 404,
  headers: {
    'access-control-allow-origin': '*',
    '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',
    'cache-control': 'max-age=0, no-cache, no-store',
    connection: 'close',
    'content-encoding': 'gzip',
    'content-length': '106',
    'content-security-policy': "default-src 'none'",
    'content-type': 'application/json; charset=utf-8',
    date: 'Sat, 07 Mar 2020 21:30:21 GMT',
    expires: 'Sat, 07 Mar 2020 21:30:21 GMT',
    pragma: 'no-cache',
    'referrer-policy': 'origin-when-cross-origin, strict-origin-when-cross-origin',
    status: '404 Not Found',
    'strict-transport-security': 'max-age=31536000, max-age=31536000',
    vary: 'Accept-Encoding',
    'x-content-type-options': 'nosniff',
    'x-frame-options': 'SAMEORIGIN',
    'x-github-enterprise-version': '2.19.4',
    'x-github-media-type': 'github.machine-man-preview; format=json',
    'x-github-request-id': '495c262c-7bdb-4341-9fb3-6f122b35e4f0',
    'x-permitted-cross-domain-policies': 'master-only',
    'x-runtime-rack': '0.015999',
    'x-xss-protection': '1; mode=block'
  },
  request: {
    method: 'POST',
    url: 'https://[REDACTED]/api/v3/app/installations//access_tokens',
    headers: {
      accept: 'application/vnd.github.machine-man-preview+json',
      'user-agent': 'octokit-rest.js/17.0.0 octokit-core.js/2.4.2 Node.js/12.16.1 (macOS Mojave; x64)',
      authorization: 'bearer [REDACTED]',
      'content-type': 'application/json; charset=utf-8'
    },
    body: '{}',
    request: { hook: [Function: bound bound register] }
  },
  documentation_url: 'https://developer.github.com/enterprise/2.19/v3'
}

I am also not sure the accept header is correct. I am under the impression that is intended to be the GitHub App name.

`requiresAppAuth()` check fails for full URLs

The following code throws an error, because it tries to retrieve an installation token, although it should just use the JWT authentication.

const octokit = new OctokitWithPagination({
  auth: {
    id: APP_ID,
    privateKey: PRIVATE_KEY
  },
  authStrategy: createAppAuth
});

const installations = await octokit.paginate("GET /app/installations", {
  mediaType: { previews: ["machine-man"] },
  per_page: 100
});

replacing

requiresAppAuth(endpoint.url)

with

requiresAppAuth(endpoint.url.replace(request.endpoint.DEFAULTS.baseUrl, ""))

fixed it for me

Add a new `log` option to `createAppAuth(options)`, then replace `console.warn` with `state.log.warn`

We are trying to avoid any direct calls to console, so that consumers of the Octokit libraries can use their own logging tool. The way we do that is a log option that is compatible with the global console object. It should at least set { debug, info, warn, error }. By default, { debug, info } are no-ops, the other two default to console.warn and console.error respectively. Compare https://github.com/octokit/core.js#logging / https://github.com/octokit/core.js/blob/37437bcf632ce32ba25663e575de96a844b802b2/src/index.ts#L111-L119

We introduced console.warn statements in #164. These should be replaced with what ever is passed as options.log.warn to the createAppAuth method.

I'd happily accept a pull request and will provide guidance if you are interested in contributing. The pull request should add a test (or adjust an existing one), it should implement the feature, and add the new option to the documentation in README.md

Dependency Dashboard

This issue contains a list of Renovate updates and their statuses.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to ignore the schedule.

  • fix(deps): lock file maintenance

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

  • build(deps): update dependency @sinonjs/fake-timers to v7

  • Check this box to trigger a request for Renovate to run again on this repository

Handle JWT errors due to out-of-sync system time

There are two errors we have to handle

  1. The calculated expiration time is in the past

    'Expiration time' claim ('exp') must be a numeric value representing the future time at which the assertion expires

  2. The issued at time is in the future

    'Issued at' claim ('iat') must be an Integer representing the time that the assertion was issued

I would catch errors in auth.hook and look for the exp or iat in the error message. If either exists, log a warning, then read out error.headers.date to get GitHub's API time, store the difference to the current system time, and use that difference moving forward when calculating more JWTs.

It can be implemented in a similar way as @octokit/auth-basics built-in request error handling:
https://github.com/octokit/auth-basic.js/blob/68dd4638631c57994be455ee7cfca7c8f0c2de8c/src/request-with-2fa.ts

If anyone would like to give this a shot, PRs welcome. I think it's a fun thing to work on. I'll need to implement this myself eventually, but it's not time critical yet

Improve error message in case of 401 after the retries in the first 5 seconds

We currently throw the standard 401 error when all the retries fail:

auth-app.js/src/hook.ts

Lines 49 to 84 in 22b88b7

/**
* Newly created tokens might not be accessible immediately after creation.
* In case of a 401 response, we retry with an exponential delay until more
* than one minute passes since the creation of the token.
*
* @see https://github.com/octokit/auth-app.js/issues/65
*/
async function sendRequestWithRetries(
request: RequestInterface,
options: EndpointOptions,
createdAt: string,
retries: number = 0
): Promise<AnyResponse> {
const timeSinceTokenCreationInMs = +new Date() - +new Date(createdAt);
try {
return await request(options);
} catch (error) {
if (error.status !== 401) {
throw error;
}
if (timeSinceTokenCreationInMs >= FIVE_SECONDS_IN_MS) {
throw error;
}
++retries;
const awaitTime = retries * 1000;
console.warn(
`[@octokit/auth-app] Retrying after 401 response to account for token replication delay (retry: ${retries}, wait: ${awaitTime}ms)`
);
await new Promise((resolve) => setTimeout(resolve, awaitTime));
return sendRequestWithRetries(request, options, createdAt, retries);
}
}

We could add more information so that users know that we send 2 or 3 retry requests to account for a potential replication lag. That way the support team will have more information they can work with when investigating the problem

/cc @gwestersf @imwiss

return type of `auth({ type: "installation", installationId, factory })` should be Promise<ReturnType<factory>>

Follow up to https://github.com/octokit/auth-app.js/pull/198/files#diff-c54113cf61ec99691748a3890bfbeb00e10efb3f0a76f03a0fd9ec49072e410aR109-R111

Currently, when doing this:

const AppOctokit = Octokit.defaults({ authStrategy: createAppAuth, });
const appOctokit = new AppOctokit({
  auth: {
    id: APP_ID,
    privateKey: PRIVATE_KEY,
  },
});

const installationOctokit = await appOctokit.auth({
  type: "installation",
  installationId: INSTALLATION_ID,
  factory: (auth) => new appOctokit.constructor({ auth }),
});

The type for installationOctokit is unknown. What it should be though is the same as the type of appOctokit.

With the way the Types for authentication strategies are currently implemented, this change will be very hard to accomplish. Unfortunately it will be quite a rabbit hole, but I think it's about time we introduce a globally declared Octokit namespace on which we can define interfaces that plugins and users can extend.

I'd declare the global Octokit namespace in https://github.com/octokit/types.ts/

declare namespace Octokit {
    export interface AuthenticationStrategies {}
}

Then each Octokit authentication strategy module could extend the interface

declare namespace Octokit {
    export interface AuthenticationStrategies {
      OctokitApp: {
        authStrategy: Strategy;
        auth: AuthOptions;
      }
    }
}

We could still use OctokitTypes.StrategyInterface with implements to make sure the API surface for each authentication strategy is compatible.

See

rename `id` option to `appId`

It will be easier to understand when using with an Octokit instance

const MyOctokit = Octokit.defaults({ authStrategy: createAppAuth })
const octokit = new MyOctokit({
  auth: {
    appId: 123,
    privateKey: PRIVATE_KEY
  }
})

is more clear than

const octokit = new MyOctokit({
  auth: {
    id: 123,
    privateKey: PRIVATE_KEY
  }
})
``

Throw error of unrecognized `type` in `.auth({ type })`

I just spend a significant amount of time debugging a problem that was ultimately caused by a space after "installation ":

octokit.auth({ type: "installation " })

We should throw an error if a type is passed that is unknown. Otherwise it currently falls back to oauth, which is not what we want.

Using with @octokit/graphql & GHES fails with 406

This is similar to #47, but when using createAppAuth.

We have some code that looks like this:

const { createAppAuth } = require('@octokit/auth-app');
const { graphql } = require('@octokit/graphql');
const { request } = require('@octokit/request');

function graphqlForInstallation(installationId) {
  const auth = createAppAuth({
    id: GITHUB_APP_ISSUER_ID,
    privateKey: PEM,
    installationId,
    request: request.defaults({
      baseUrl: `${GITHUB_BASE_URL}/api/v3`,
    }),
  });
  const graphqlWithAuth = graphql.defaults({
    baseUrl: GITHUB_BASE_URL,
    request: {
      hook: auth.hook,
    },
  });
  return graphqlWithAuth;
}

When this is used with public GitHub it works okay. However, when it is used with GHE v2.18 (specifically tried with 2.18.20), we get an error with the following stack trace (partial, starting at @octokit/auth-app code):

TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at set (/usr/src/app/node_modules/@octokit/auth-app/dist-node/index.js:65:63)
    at getInstallationAuthentication (/usr/src/app/node_modules/@octokit/auth-app/dist-node/index.js:161:9)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async hook (/usr/src/app/node_modules/@octokit/auth-app/dist-node/index.js:280:7)

I looked into applying the workaround mentioned in #47, but after reading through some of the code here, I think that may not be possible at this time.

Looking at the stack trace, the problem seems to be when octokit is getting installation authentication via the request auth hook

    at getInstallationAuthentication (/usr/src/app/node_modules/@octokit/auth-app/dist-node/index.js:161:9)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async hook (/usr/src/app/node_modules/@octokit/auth-app/dist-node/index.js:280:7)

I believe that is called right here:

const { token } = await getInstallationAuthentication(state, {}, request);

This is calling getInstallationAuthentication with {} as the second argument. Here's the signature:

export async function getInstallationAuthentication(
state: StrategyOptionsWithDefaults,
options: InstallationAuthOptions,
customRequest?: RequestInterface
): Promise<InstallationAccessTokenAuthentication> {

The second argument here is options, which is where it pulls permissions when making the request:

} = await request("POST /app/installations/:installation_id/access_tokens", {
installation_id: installationId,
repository_ids: options.repositoryIds,
permissions: options.permissions,

So since createAppAuth or the hook do not provide a way for us to specify this permissions option, I don't think we can use this workaround with createAppAuth.

Is there an alternative approach we could use here, or would you be open to making a change to this package to make this work?

An in-range update of fetch-mock is breaking the build 🚨

The devDependency fetch-mock was updated from 8.2.1 to 8.3.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

fetch-mock is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details

Commits

The new version differs by 22 commits.

  • 6290ca4 Merge pull request #491 from wheresrhys/matcher-object
  • e7e6503 reorg
  • a613d8f update types
  • 110e001 improve exaples
  • a2f75f6 better documentation of complex matcher patterns
  • 84c95a4 documentation update
  • 3b239cc Merge pull request #492 from wheresrhys/refactor-for-obj-matcher
  • 125a178 tidy
  • 3294162 fixed all tests
  • 815eb1b begininng to refactor tests
  • a6a3c80 fix test ad lint
  • befeef4 remove logs
  • fbadda5 converted most behaviour to separate url from other matchers
  • 7680d9e tests for a matcher object
  • 96a76f2 Update resetHistory.md

There are 22 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Replace "cdn.pika.dev" with "cdn.skypack.dev" in README

πŸ†•πŸ₯☝ First Timers Only.

This issue is reserved for people who never contributed to Open Source before. We know that the process of creating a pull request is the biggest barrier for new contributors. This issue is for you πŸ’

About First Timers Only.

πŸ€” What you will need to know.

The Pika CDN is now Skypack, see https://www.pika.dev/cdn. The CDN at https://cdn.pika.dev/ no longer works, all URLs must be replaced with the new CDN: https://cdn.skypack.dev/. We currently recommend using cdn.pika.dev to import the library into the browser, but that no longer works. Replacing it with cdn.skypack.dev will make it work again.

πŸ“‹ Step by Step

  • πŸ™‹ Claim this issue: Comment below.

    More than one person can work on this issue, don't worry if it's already claimed.

  • πŸ“ Update the file \README.md (press the little pen Icon) and edit as shown below:

@@ -32,11 +32,11 @@ For other GitHub authentication strategies see [octokit/auth.js](https://github.
 Browsers
 </th><td width=100%>
 
-Load `@octokit/auth-app` directly from [cdn.pika.dev](https://cdn.pika.dev)
+Load `@octokit/auth-app` directly from [cdn.skypack.dev](https://cdn.skypack.dev)
 
 ```html
 <script type="module">
-  import { createAppAuth } from "https://cdn.pika.dev/@octokit/auth-app";
+  import { createAppAuth } from "https://cdn.skypack.dev/@octokit/auth-app";
 </script>
 ```
 
  • πŸ’Ύ Commit your changes

  • πŸ”€ Start a Pull Request. There are two ways how you can start a pull request:

    1. If you are familiar with the terminal or would like to learn it, here is a great tutorial on how to send a pull request using the terminal.
    2. You can edit files directly in your browser
  • 🏁 Done Ask for a review :)

If there are more than one pull requests with the correct change, we will merge the first one, but attribute the change to all authors who made the same change using @Co-authored-by, so yo can be sure your contribution will count.

πŸ€”β“ Questions

Leave a comment below!

This issue was created by First-Timers-Bot.

"factory" option for auth method to create a new instance with shared state

When authenticating using an app ID and private key, there is currently no simple way to derive a new octokit instance which is authenticated as an installation. When implementing a GitHub App which acts on webhook events, we currently have to

  1. Create an octokit instance with app authentication ({ id, privateKey })
  2. For each event, create a new octokit instance to which we have to pass the previous app auth options as well as installationId ({ id, privateKey, installationId })
  3. Use an external cache instance so that the installation access tokens can be cached across all these instances

In order to get octokit instances for the App and for each installation with a shared cache, something like this is required

const { Octokit } = require("@octokit/core");
const { createAppAuth } = require("@octokit/auth-app");

const CACHE = {};
const globalTokenCache = {
  async get(key) {
    return CACHE[key];
  },
  async set(key, value) {
    CACHE[key] = value;
  },
};

const MyAppOctokit = Octokit.defaults((options = {}) => {
  const defaults = {
    authStrategy: createAppAuth,
    auth: {
      id: process.env.APP_ID,
      privateKey: process.env.APP_PRIVATE_KEY,
      cache: globalTokenCache,
    },
    userAgent: "my-app/1.2.3",
  };

  if (options.auth) {
    defaults.auth.installationId = options.auth.installationId;
  }

  return defaults;
});

const appOctokit = new MyAppOctokit()
const installationOctokit = new MyAppOctokit({ auth: { installationId: 123 } })

What would greatly simplified the above code, but achieve the same thing, would be

const { Octokit } = require("@octokit/core");
const { createAppAuth } = require("@octokit/auth-app");

const MyAppOctokit = Octokit.defaults({
  authStrategy: createAppAuth,
  auth: {
    id: process.env.APP_ID,
    privateKey: process.env.APP_PRIVATE_KEY,
  },
  userAgent: "my-app/1.2.3",
});

const appOctokit = new MyAppOctokit();
const installationOctokit = await appOctokit.auth({ type: "installation-octokit", installationId: 123 })

In order for that to be possible, we have to add a new Octokit strategy option, and @octokit/core will have to set it to this.constructor in https://github.com/octokit/core.js/blob/c44da9b6a3ea3edc7882c9f776639215a6f53bca/src/index.ts#L138-L145

atob is not defined when building with target: Node using webpack

Hello,

I'm facing this error when I try to request the API. My project uses the following packages:

  • "@octokit/auth-app": "^2.4.4"
  • "@octokit/rest": "^17.1.4"
  • "typescript": "^3.8.2"
import { createAppAuth } from "@octokit/auth-app";
import { Octokit } from "@octokit/rest"

const appOctokit = new Octokit({
  authStrategy: createAppAuth,
  auth: {
    id: APP_ID,
    privateKey: PRIVATE_KEY
  }
})
const { data } = await appOctokit.request("/app");
console.log(data)
"errorType": "ReferenceError",
"errorMessage": "atob is not defined",
"stack": [
    "ReferenceError: atob is not defined",
    "    at getDERfromPEM (/var/task/webpack:/myapp/node_modules/universal-github-app-jwt/dist-web/index.js:15:1)",
    "    at getToken (/var/task/webpack:/myapp/node_modules/universal-github-app-jwt/dist-web/index.js:50:1)",
    "    at githubAppJwt (/var/task/webpack:/myapp/node_modules/universal-github-app-jwt/dist-web/index.js:71:1)",
    "    at getAppAuthentication (/var/task/webpack:/myapp/node_modules/@octokit/auth-app/dist-web/index.js:8:37)",
    "    at getInstallationAuthentication (/var/task/webpack:/myapp/node_modules/@octokit/auth-app/dist-web/index.js:110:1)",
    "    at dist_web_hook (/var/task/webpack:/myapp/node_modules/@octokit/auth-app/dist-web/index.js:240:20)",
    ...
]

I tried to install the package atob-lite cause it was a dependency in the past https://github.com/octokit/rest.js/pull/1302, but it doesn't fix the issue.

Throw helpful error is installationId is unset

I'm following this basic example and I'm getting the JWT back fine but I'm getting a 404 for the installation access token. Tried hitting the api directly too, getting a 404 from there as well.

  • using the right private key, checked the fingerprint
  • tried making the app / repo public
  • the app id is definitely correct
  • checked the signature of the generated JWT

but still calling this endpoint responds with 404

curl -i -X POST
-H "Authorization: Bearer YOUR_JWT"
-H "Accept: application/vnd.github.machine-man-preview+json"
https://api.github.com/app/installations/:installation_id/access_tokens

Can't work out what I'm missing here would appreciate any help

Getting the `installation_id` for an existing installation

I am not sure if this is outside of the scope of this project (or event the Github REST API) but is it possible to get the installation_id for an existing install?

The flow I have works while the app is uninstalled, I then prompt the user to install, they are redirected back with the installation_id in the query string and I can use that to do an install like so:

// Express middleware...
const setupOctokit = ({ options = {} } = {}) => (request, response, next) => {
    const { githubInstallationId: installationId } = request.body;

    const octokit = new Octokit({
        ...options,
        ...(installationId && {
            authStrategy: createAppAuth,
            auth: {
                installationId,
                privateKey: key,
                id: process.env.API_GH_APP_ID,
            },
        })
    });

    request.octokit = octokit;

    next();
}

And then proceed from there, however I do not persist the installation_id anywhere (I am trying to do the whole flow DB free). Now the problem is I cannot get the installation_id on subsequent visits to the site, if I prompt the user to install again it takes them to the Github page where they can manage the app, ideally I was hoping Github would just redirect already authenticated apps back to the client with the query string a second time.

I believe this probot issue may be some what related, and this Github community post is almost exactly the same issue as I am having.

Throw a descriptive error when permissions is not set

Hello,

I ran into an issue where when I did not set a permissions object, even an empty one, in the the auth options I would see the following error:

Cannot convert undefined or null to object

Upon debugging it seems as if it comes from here:

: Object.keys(data.permissions)

If no permissions are passed in, the Object.keys throws the Cannot convert undefined or null object.

It was not clear from the documentation that the permissions object is required. Examples in the documentation seem to leave that out.

Small Reproducer

const auth = createAppAuth({
  id: 123,
  privateKey: `-----BEGIN RSA PRIVATE KEY-----...`,
  installationId: 456,
});

const installationAuthentication = await auth({
  type: 'installation',
  // permissions: {}, // This is what I added to make it work
});

How to create a repository by Github App?

I went through Github API and found some API that we could create a repository like:

https://docs.github.com/en/rest/reference/repos#create-a-repository-using-a-template
https://docs.github.com/en/rest/reference/repos#create-an-organization-repository
https://docs.github.com/en/rest/reference/repos#create-a-repository-for-the-authenticated-user

But it seems for only OAuth App that we need to scope repo permission on that.

I wonder is there a way we can do it on Github App with some kind of app token or installation token? If that we could install the new repository to the App also. It could be amazing fit to my use case.

An in-range update of fetch-mock is breaking the build 🚨

The devDependency fetch-mock was updated from 9.0.0 to 9.1.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

fetch-mock is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… test (12): null
  • ❌ test (10): There are 2 failures, 0 warnings, and 0 notices.
  • βœ… test (8): null

Commits

The new version differs by 3 commits.

  • db7ecbd Merge pull request #509 from wheresrhys/partial-body-matching
  • 6a8f3ea tidy up internal fetching of config
  • 8683967 implement partial body matching

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of @octokit/request-error is breaking the build 🚨

The dependency @octokit/request-error was updated from 1.2.0 to 1.2.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@octokit/request-error is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details

Release Notes for v1.2.1

1.2.1 (2020-01-30)

Bug Fixes

  • package.json built by latest pika version (0.8.1) (346b69a)
FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.