DEV Community

Olivier Miossec
Olivier Miossec

Posted on

How to authenticate to the GitHub REST API with PowerShell

The GitHub REST API is an essential tool to automate your GitHub repositories. You can use it to create issues, manage branches, create dashboards, or many other things.
We can use PowerShell to automate all these tasks and create applications that automate to work for us. Let's see how to start.

For using the Rest API with PowerShell, we need to authenticate to the Rest API. You cannot do it using a Login/Password, it will not work, and you will get a 4XX HTTP error.

There are 3 ways to authenticate to the Rest API, access token, GitHub App, and inside GitHub Action.

Access token

Access token is the simple way to authenticate to the Rest API. You simply need to go to your GitHub account settings then Developer Settings (or simply go to this URI), and then create an access token. You can either choose the classic tokens (no restriction) or the fine-grained token where you can use fine-tuned permissions.

I will create a classic token with the repo:status and write:discussion privileges.
To use the token follow the script here

# This script illustrates how you can log in and perform a get action to Github Rest API with an access token 
# This script lists all repository names for a given organization

param(
    # The access token to the GitHub Rest API 
    [Parameter(Mandatory=$true)]
    [string]
    $accessToken, 

    [Parameter(Mandatory=$true)]
    [string]
    $orgaName
)

$authenticationToken = [System.Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$accessToken"))
    $headers = @{
        "Authorization" = [String]::Format("Basic {0}", $authenticationToken)
        "Content-Type"  = "application/json"
    }

$reposAPIUri = "https://api.github.com/orgs/$($orgaName)/repos"

$githubRepositories = Invoke-RestMethod -Method get -Uri $reposAPIUri -Headers $headers 

foreach ($respository in $githubRepositories) {
    write-host  $respository.name
}
Enter fullscreen mode Exit fullscreen mode

The token is encoded in Base64

Then formatted to give something like
Authorization Basic
End added to the http header for in the invoke-RestMethod cmdlet

GitHub App

Authentication with a GitHub App is more complex. First, you need to create a GitHub App by following the instructions on this page. Once you have created your GitHub App you will need to create a client secret and a private key. Download the private key on your computer. And finally note the App ID.

You will also need to install the application in your account and get the instance ID.

To authenticate with a GitHub app you will need to authenticate first with the certificate and then generate a token to access the API.
The certificate and the App ID will be used to create a JSON Web Token. This JWT will be used to create a JIT token for the GitHub Rest API request.

To create the SWT I need a tool, there are no native tools to create a JWT in PwSh now, but you can use the powershell-jwt module as I did here (install-module -name powershell-jwt)

With the access token, you can query the API by using the Authorization="token $token", note that you can also ask for a specific version of the API by using the X-GitHub-Api-Version

Note also that GitHub recommends using Accept="application/vnd.github+json" when interacting with the API.

# This script illustrates how you can log in and perform a get action to Github Rest API with a GitHub App 
# this script list all issues 

param(
    # The access token to the GitHub Rest API 
    [Parameter(Mandatory=$true)]
    [string]
    $pathToGitHubAppKey, 

    [Parameter(Mandatory=$true)]
    [string]
    $instanceID, 

    [Parameter(Mandatory=$true)]
    [string]
    $appID, 

    [Parameter(Mandatory=$true)]
    [string]
    $organisation, 

    [Parameter(Mandatory=$true)]
    [string]
    $repository
)


# Get the private key content
$apiPemData = Get-Content -Path $pathToGitHubAppKey
$apiSecret = [System.Text.Encoding]::UTF8.GetBytes($apiPemData)

$exp = [int][double]::parse((Get-Date -Date $((Get-Date).addseconds(300).ToUniversalTime()) -UFormat %s)) 
$iat = [int][double]::parse((Get-Date -Date $((Get-Date).ToUniversalTime()) -UFormat %s)) 

# create a Json Web Tokken using new-jwt from the powershell-jwt module
$jwt = New-JWT -Algorithm "RS256" -Issuer $appID -ExpiryTimestamp $exp -SecretKey $apiSecret -PayloadClaims @{ "iat" = $iat}


# request a new tokken 
$headers = @{
    "Accept" = "application/vnd.github+json"
    "Authorization" = "Bearer $jwt"
}

$res = Invoke-WebRequest -Uri "https://api.github.com/app/installations/$($instanceID)/access_tokens" -Headers $headers -Method Post
$json_res = ConvertFrom-Json($res.Content)
$token = $json_res.token


# Querry the API to list all issues in a repository
$reposAPIUri = "https://api.github.com/repos/$'$organisation)/$($repository)/issues"

$headers = @{
    Accept="application/vnd.github+json"
    Authorization="token $token"
    "X-GitHub-Api-Version" = "2022-11-28"
}
$issuesList = Invoke-WebRequest -Uri $reposAPIUri  -Headers $headers

$issuesObject = ConvertFrom-Json($issuesList.content)

foreach ($issue in $issuesObject) { 
    $issue.title 
}
Enter fullscreen mode Exit fullscreen mode

GitHub Action workflow

The last way to authenticate to the Rest API is to run your PowerShell script in GitHub Action. You can use the Token method or the GitHub method to authenticate to GitHub Rest API. But GitHub doesnโ€™t recommend that.
When you create a workflow for GithHub Action, GitHub creates a token, GITHUB_TOKEN, that you can use in your script.
The first step is to create the workflow with the main.yaml file

name: Windows-wks

on: [push, pull_request]

jobs:
  validate:
    runs-on: windows-latest
    permissions: 
      issues: write
    env: 
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

    steps:
      - uses: actions/checkout@v1
      - name: Perform_Tests
        shell: pwsh
        run: .\githubAction-login.ps1
Enter fullscreen mode Exit fullscreen mode

In the Job, you can setup permissions for the built-in token

    permissions: 
      issues: write
Enter fullscreen mode Exit fullscreen mode

Then I add the token to an environment variable

    env: 
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

So, I can use it in the script like this

$stringTokken = $Env:GH_TOKEN

    $headers = @{
        "Accept" = "application/vnd.github+json"
        "Authorization" = "Bearer $stringTokken"
    }

$reposAPIUri = "https://api.github.com/repos/<ORGA>/<REPOS>/issues"

$githubRepositories = Invoke-RestMethod -Method get -Uri $reposAPIUri -Headers $headers 

foreach ($respository in $githubRepositories) {
    write-host  $respository.name
}
Enter fullscreen mode Exit fullscreen mode

You can use the token as is, no need to encode it

Top comments (0)