Dumb question about GitHub Apps but it isn't quite clear!


#1

I’m confused about how a GitHub app can distinguish between different users of the app.

I created an experimental GitHub App, I can see now that in my user Settings under Developer Settings under GitHub Apps the app is listed.

I can click the app name and see the app’s configuration (url, callback url, webhook url etc) at the bottom I can also see details about the private key (which I have generated in my case) as well as client-id and client-secret.

So does the above define the App itself in GitHub, is this distinct from any usage of that app?

I can see also under the Settings for one of my repos that the app is listed under Integration and Services (I of course did this) and I can configure the app by pressing Configure. In there I’ve given the app read access to this repo.

Is this definition purely concerned with my specific usage of the app? rather than anything to do with the app itself?

What’s not clear to me is that it is the app itself that has a private key, client_id and client_secret not the particular installation of the app, so how does the app associate what it does (API calls etc) with the specific user account that an app user wants to target?

I read about authenticating as an installation but still not really clear on how - after do that - we can identify the specific user who the app may be acting on behalf of.

Is it the case that this doesn’t matter? After we get the “installation access token” is that all we need? if the user of the app tries to access this or that repo is it GitHub that checks to see if the app is installed on that repo and what permisisons are set etc?

Also I was studying this webhooks article earlier and that acquires access by leveraging an “installation ID” which is sent as part of the webhook event payload, but what if we want to initiate access from the app without any webhook being involved? in such a case where would we get an installation id?

Thanks!


#2

I think I’m as confused as you are about Github Apps authentication.
I wanted to build a Github app and so I first saw GraphQL and figured I should use it over the old REST API. And so I read about authenticating as an installation and that seemed to make the most sense. I would think that there is a rate limit per installation instead of per user but I’m uncertain.

The only problem with the installation method is it expires every hour and I have not yet found a smart way to renew this without regenerating the JWT and I don’t yet have a way to get the installation ID in a automated way.

You may also noticed like me that when you read the docs it says you have to use REST v3 for github apps which is confusing since why can I authenticate as an installation if you aren’t suppose to use GraphQL for Github Apps.

It makes me think you can but there is no support or there might be hard limits that I will reach will prevent me from using GraphQL eg. Rate Limiting, Frequent Authentication. It appears the GraphQL API has been around for a few years which makes me think it would be usable for Github Apps.

The I looked at Octokit and working with REST you’re forced to make so many queries, Which I guess if one oAuth user is allowed to make 5000 per hour I guess you should be able to get all the data you need.

I know this isn’t an answer but thought talking out loud might shake something loose.

require 'yaml'
require 'openssl'
require 'jwt'
require 'rest-client'
require 'json'
require 'pp'

class Query
  INSTALL_ID = 102956
  def self.generate_jwt
    private_pem = File.read '/Users/andrew/Sites/swimmer_ext/swimmer.2018-03-08.private-key.pem'
    private_key = OpenSSL::PKey::RSA.new private_pem
    payload = {
      iat: Time.now.to_i,             # issued at time
      exp: Time.now.to_i + (10 * 60), # JWT expiration time (10 minute maximum)
      iss: 9839 # GitHub App's identifier
    }
    JWT.encode payload, private_key, "RS256"
  end

  def self.generate_access_token
    jwt = self.generate_jwt
    url = "https://api.github.com/installations/#{INSTALL_ID}/access_tokens"
    headers = {
      :Authorization => "Bearer #{jwt}",
      :Accept        => "application/vnd.github.machine-man-preview+json"
    }
    response = RestClient.post url, nil, headers
    data     = JSON.parse response.body
    data["jwt"] = jwt
    data
  end

  def self.save_to_yaml data
    File.open("access.yml","w") do |file|
     file.write data.to_yaml
    end
  end

  def self.load_from_yaml
    YAML.load(File.read("access.yml"))
  end

  def self.query query
    access  = self.load_from_yaml
    url     = 'https://api.github.com/graphql'
    headers = { :Authorization => "Bearer #{access['token']}" }
    payload = { query: "query {#{query}}" }.to_json
    begin
      response = RestClient.post url, payload, headers
      data     = JSON.parse response.body
      pp data
    rescue RestClient::ExceptionWithResponse => e
      puts "ERROR: " + e.message
    end
    data
  end

end

#3

So now doing more reading I think authentication Installation can only perform a limited amount of actions

As it says

Accessing API endpoints as an installation
For a list of REST API v3 endpoints that are available while authenticated as an installation, see "Available Endpoints."

The Available Endpoints are here
https://developer.github.com/v3/apps/installations/

So those endpoints are limited to very basic things like adding, removing a repo to an installation or listing out repos that have an installation installed.

Now this is confusing because I remember when I installed my github app it asked what permissions it should be allowed to access to making me think the scope of accessible API is wider than what they say is available.

Other than for read access it appears I will have to use REST API since there are post and put actions I simply cannot do via GraphQL mutations

repository(owner: "omenking", name: "swimmer") {
  assignableUsers(first: 100){
    edges {
      node {
				login
        name
        avatarUrl
      }
    }
  }
  project(number: 1) {
    columns(first: 100) {
      edges {
        node {
          id
          name
          cards(first: 100) {
            edges {
              node {
                content {
                  ... on Issue {
                    id
                    number
                    title
                    body
                    author {
                      login
                    }
                    assignees(first: 1) {
                      edges {
                        node {
                          login
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

#4

@omenking - Hi Andrew thanks for posting that it all helps me as I research this whole area. Frankly I think the documentation is no doubt technically correct but seems to presume a certain level of familiarity from the developer which in this specific area I have very little.

I do know that Octokit are close to merging a PR that exposes new support specifically for GitHub app so I’ll jump on this once its merged.

It would really help to have more abstract explanation of the differences between a GitHub App and an OAuth App as well as the options each has available for authenticating.

Saying we can have a GitHub App and an OAuth App and then in the next sentence saying a GitHub App can authenticate using OAuth is rather confusing to me.

I think a page or two about each type of app and each type of authentication each may use together with examples use cases of each type of authentication in each type of app would be a great help.

I also found that one API was labelled as being supported for GitHub Apps but then when I tried to access it from an experimental GitHub App which was authenticating with OAuth (that is using the redirect to GitHub to get approval approach) it failed and I was told (in some other recent post of mine) that it isn’t supported for GitHub Apps which have used OAuth!

So its not sufficient to say this or that endpoint is or is not supported for use by GitHub Apps because it also depends upon the authentication method that was used - perhaps some form of tabular summary of this would also help in the documentation.

If anyone from GitHub is reading please understand this is all intended to be constructive, I’m doing some good stuff with GitHub and its API but just having trouble establishing a solid base structure for my GitHub App.

FYI my app will be developed using ASP.NET Core and I need to FULLY understand EXACTLY what all this is about before I can create my agnostic shell application, Ideally I’ll create some basic framework that I can use going forward for any new GitHub App I need to develop.


#5

Oauth Apps

An app for the purpose of using as a method of authenication for
your web-app/site eg. login/signup

Github Apps

An app that uses the github api which could be in the context of
a anonymous user, a user’s perceptive or the perceptive of an installed
application.

Oauth Authenication

Authenicates from the perceptive of a user
User Permissions

Installation Authenication

Authenicates from the perceptive of an installation
Installation Permissions

Confusion for me

I am building a chrome extension that adds swimlanes functionality to Github Projects.
I was thinking that I need to authenicate from the installation permissions where its installed
with specific repo permission so I can look up Projects, ProjectColumns, ProjectCards and Issues.
I already do that without too much trouble.

When a user moves a card from lane to lane I would then fire a request to my server which would then
from the Installation perceptive update the card

I could think that I might want to authenicate from the user, but my feeling is that their will be permission restrictions such as maybe I can’t add ProjectColumns.

Since my app is intended for the org instead of then an individaul user we really only want to install once and spare all the other uses from using Oauth. Though I want to Oauth each user so I can keep track
of each user’s indivual actions even if they get trigger through the Installation perceptive

Its possible that there are separate rate limits from the User’s perceptive and Installation perceptive so I might want to mix and match actions to avoid hitting rate limit


#6

Hey @Korporal, @omenking

So does the above define the App itself in GitHub, is this distinct from any usage of that app?

Yes, the section you described above in Developer Settings > GitHub Apps > <your_app> is the definition of a GitHub App. We refer to the term “installation” as any usage of a given App (effectively, granting an App access, depending on the permissions, to resources within a user account, or within an Organization.

Is this definition purely concerned with my specific usage of the app? rather than anything to do with the app itself?

Yes, this is the so called Installation, the realisation of a user/organization granting access of this GitHub App to their resources.

What’s not clear to me is that it is the app itself that has a private key, client_id and client_secret not the particular installation of the app, so how does the app associate what it does (API calls etc) with the specific user account that an app user wants to target?

The private key, client_id and client_secret are used by the application to authenticate itself. What in means, as opposed to what happens in the case of OAuth, is the application here acting in behalf of itself, not in the name of the user.

Is it the case that this doesn’t matter? After we get the “installation access token” is that all we need? if the user of the app tries to access this or that repo is it GitHub that checks to see if the app is installed on that repo and what permissions are set etc?

By authenticating as an installation, you can make use of GitHub APIs not only in the name of an application, but more specifically in the name of a given installation (bound to user/organization). When a user interacts with GitHub, it will trigger events and your application will get notified, granted subscription to the corresponding events have taken place. These events will contain as part of the even payload information about the installation that triggered it. Your application can then react to these events acting in behalf of the application installation. It’s the installation who is granted to access user/organization resources.

Also I was studying this webhooks article earlier and that acquires access by leveraging an “installation ID” which is sent as part of the webhook event payload, but what if we want to initiate access from the app without any webhook being involved? in such a case where would we get an installation id?

Installation IDs for your application can be queried from GitHub’s API via the se the /app/installations endpoint documented at https://developer.github.com/v3/apps/#find-installations

You can find more information about OAuth Apps vs GitHub Apps here:
https://developer.github.com/v3/apps/#find-installations


#7

@vroldanbet This is much appreciated Victor, it certainly clarifies some grey areas for me, many thanks for the post!