Join our Newsletter — 33% off our NHI Course
Home› Guides› GitHub Apps vs Personal Access Tokens vs OAuth…
Guide Non-Human Identity (NHI)

GitHub Apps vs Personal Access Tokens vs OAuth Apps: Which Identity to Use

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 13 November 2026 16 min read
On this page

Most GitHub automation still runs on a personal access token belonging to whoever set it up, which means the integration's reach, lifetime and audit trail are those of a person rather than a machine. GitHub offers three identities for code that calls its API: GitHub Apps, personal access tokens (PATs, in fine-grained and classic forms) and OAuth apps. They differ in who the activity is attributed to, how far access reaches, how long credentials live and who in the organisation controls them. This guide gives the short answer, a side-by-side comparison, a threat model and controls for each option, worked scenarios and a decision checklist. It is for platform engineers, DevOps and security teams choosing an identity for CI, bots, internal tools and third-party integrations, and for reviewers deciding whether an existing integration should be migrated.

This is an independent guide from NHI Mgmt Group, based on GitHub's public documentation as of November 2026. It is not sponsored or reviewed by GitHub. Product features change, so confirm settings against GitHub's current documentation.

Key takeaways

  • Default to a GitHub App for anything long-lived. GitHub's own guidance recommends a GitHub App for long-lived integrations and over OAuth apps generally: fine-grained permissions, installer-chosen repositories and installation tokens that expire after one hour.
  • PATs are for people and short-lived scripts. A PAT is tied to its creator and stops working when that user loses access, so automation built on one inherits a person's lifecycle and blast radius.
  • Choose fine-grained over classic. A classic PAT reaches every repository its user can access; a fine-grained PAT is limited to one owner, selected repositories and specific permissions, and organisations can require approval.
  • OAuth apps always act as the user. They use broad scopes such as repo, reach everything the authorising user can see and, by default, issue tokens that last until revoked.
  • Inside Actions, use neither. For workflows, use the built-in GITHUB_TOKEN with minimal permissions, and OIDC federation for cloud access; reach for a GitHub App token only when the workflow needs more than GITHUB_TOKEN can grant.

The short answer

Use caseUseWhy
Bot, CI service, internal tool or integration acting for the organisationGitHub App, authenticating as an installationActivity attributed to the app, repository-scoped, one-hour tokens, survives staff changes
Tool that must act as the signed-in user (code review UI, developer portal)GitHub App with user access tokensActions limited to what both the app and the user can do; tokens can expire and refresh
Workflow inside one repositoryGITHUB_TOKEN with explicit permissionsCreated per job and scoped to the repository; no stored secret
One-off script, API testing, personal toolingFine-grained PAT with expiryQuick to create, limited to selected repositories and permissions
Feature only classic PATs support (some outside collaborator and public-repository contribution cases, Packages)Classic PAT, minimal scopes, short expiry, recorded exceptionNo better option for that specific call; contain it
Existing third-party product that only offers OAuthOAuth app, approved by an owner under OAuth app access restrictionsAccept with compensating controls; ask the vendor for a GitHub App

Side-by-side comparison

The facts below are taken from GitHub's documentation on the differences between GitHub Apps and OAuth apps, on managing PATs and on REST API rate limits.

PropertyGitHub AppFine-grained PATClassic PATOAuth app
Acts asItself (a name[bot] account) or on behalf of a userThe creating userThe creating userThe authorising user, always
Permission modelFine-grained read or write per permissionFine-grained per permissionBroad scopesBroad scopes (e.g. repo for issues or pull requests)
Repository reachRepositories chosen at installationOne resource owner; all or selected repositoriesEverything the user can access, across organisationsEverything the authorising user can access
Credential lifetimeInstallation tokens expire after one hour; user tokens can expire and be refreshedSet by the creator; organisations can cap it (default cap 366 days)Set by the creator; no cap by default; removed after a year unusedLong-lived by default; optional eight-hour expiring user tokens with refresh
Long-term secretApp private key (up to 25 per app, no expiry)The token itselfThe token itselfClient secret plus each user's token
Organisation controlOwners install and choose repositories; owner approval for organisation permissionsOrganisation can require admin approval (default) and restrict accessOrganisation can restrict access; no approval flowOAuth app access restrictions (on by default for new organisations) require owner approval
When the creator leavesKeeps working (owned by the organisation if created there)Stops working when the user loses accessStops working when the user loses accessThat user's tokens stop working
REST rate limit5,000 per hour minimum per installation, scaling to 12,500 (15,000 on Enterprise Cloud)User's 5,000 per hourUser's 5,000 per hourUser's 5,000 per hour
WebhooksOne built-in webhook, disabled on uninstallNoneNonePer repository or organisation, needs hook scopes, not cleaned up automatically
Token prefixghs_ installation, ghu_ user, ghr_ refreshgithub_pat_ghp_gho_

The prefixes matter for detection: secret scanners and your own log searches can tell at a glance which kind of identity leaked. For a wider look at token types, see the API Keys vs OAuth Tokens Guide.

GitHub Apps

Architecture in words

A GitHub App is a registered identity with its own permissions and a private key. The app's backend signs a JSON Web Token (JWT) with that key, using RS256, with an expiry no more than 10 minutes ahead; GitHub recommends setting the issued-at time 60 seconds in the past to absorb clock drift. The JWT lets the app act as itself, for example to list installations, and to request an installation access token for a specific installation. That installation token carries only the permissions and repositories granted when an owner installed the app, and expires after one hour. Activity is attributed to the app's bot account. Alternatively, the app can obtain a user access token through a user's sign-in, and then acts only where both the app and the user have access.

Threat model

  • Private key theft: the key is the crown jewel. Anyone holding it can mint installation tokens for every installation of the app until the key is deleted, because keys do not expire. This maps to T1552.001 Credentials In Files when keys are left in repositories or images.
  • Over-broad installation: installing on "All repositories" when the app needs three, or granting write where read would do.
  • Multi-tenant apps: a third-party app installed across many customers concentrates risk in its vendor's backend; compromise there yields tokens for every customer installation.
  • Token replay within the hour: a stolen installation token is usable until it expires (T1550.001 Application Access Token), which limits but does not remove exposure.

Controls

  • Key custody: GitHub's guidance is to keep the private key in a key vault configured sign-only, never hard-coded even in a private repository; environment variables are weaker. Keep two keys so a compromised one can be deleted without downtime (up to 25 keys per app).
  • Least privilege: request only the permissions used, install on selected repositories, and review installations when the app's code changes its needs.
  • Ownership: register organisation apps under the organisation, not a personal account, and record a technical owner.
  • Token handling: request installation tokens just in time, optionally narrowed to specific repositories and permissions at request time, and do not cache them beyond use.

Failure modes

Keys pasted into CI variables and forgotten; one app shared across unrelated systems so its permissions become the union of all needs; installations left on repositories after a project ends.

Personal access tokens

Architecture in words

A PAT is a bearer secret that stands in for a password when a user calls the API or Git over HTTPS. A classic PAT carries scopes and reaches every repository the user can access, in every organisation. A fine-grained PAT is bound to one resource owner (a user or an organisation), lists all or selected repositories, and carries specific permissions; a user can hold up to 50. Neither type can exceed the creator's own access, and both become inactive if the creator loses access to the resource. GitHub removes classic PATs unused for a year.

Threat model

  • Leak in code or CI: PATs are long-lived strings that end up in repositories, logs and workflow secrets. The SpotBugs token leak began when a maintainer's personal token was added to a workflow that ran code from pull requests, and the stolen token led on to other projects months later.
  • Blast radius of a person: a classic PAT belonging to an organisation owner carries owner-level reach across every organisation they belong to.
  • Attribution gap: actions appear as the user, so automated changes and human changes are indistinguishable without token data in the audit log.
  • Lifecycle coupling: automation breaks when the person leaves, which pushes teams to keep leavers' accounts alive or to share accounts.

Controls

  • Organisation PAT policy: restrict classic PAT access to organisation resources, keep "Require administrator approval" for fine-grained tokens (the default), and set maximum lifetimes for both types; GitHub blocks non-compliant tokens rather than revoking them. See How to set expiry policies on personal access tokens.
  • Use alternatives for people: GitHub suggests GitHub CLI or Git Credential Manager for command-line access instead of hand-made PATs.
  • Push protection: block tokens from being committed at all; see How to enable GitHub secret scanning push protection.
  • Machine users as a last resort: where a PAT must drive automation, a dedicated machine account with a fine-grained token is better than a person's token, but it is still a shared credential to govern. See How to audit GitHub outside collaborators and machine users.

Detailed PAT hardening is in the GitHub Personal Access Tokens Security Guide.

Failure modes

Non-expiring tokens created "temporarily"; a fine-grained PAT set to all repositories; classic PATs kept because one endpoint needed them, then reused everywhere.

OAuth apps

Architecture in words

An OAuth app is a registered client with a client ID and secret. A user signs in and authorises requested scopes; the app receives an access token that acts as that user, with the user's identity on every action. Scopes are coarse: reading issues or pull requests requires repo, which also grants code access. The token reaches everything the user can access, and lasts until revoked unless the app opts into eight-hour expiring tokens with refresh tokens. Webhooks have to be created per repository or organisation with hook scopes and are not removed when access ends.

Threat model

Controls

  • Keep OAuth app access restrictions on: they are enabled by default for new organisations. Members can then only request access, and owners approve. Unapproved apps lose access to private organisation resources.
  • Prefer expiring tokens: where you build or configure an OAuth app, turn on expiring user tokens.
  • Review approved apps: scopes, last use and owner, at least quarterly; see How to audit GitHub Apps and OAuth apps in an organisation.
  • Ask for a GitHub App: when a vendor offers both, choose the GitHub App; when it offers only OAuth, record it as an exception with a review date.

Failure modes

Restrictions turned off to unblock one team and never re-enabled; app approved for an organisation owner, which gives it everything visible to the owner's token in that organisation.

What about GITHUB_TOKEN and OIDC

Two further identities often replace all three options above in CI. Each workflow job gets a GITHUB_TOKEN scoped to its repository; set permissions explicitly at workflow or job level so it carries only what the job needs (see How to Restrict GITHUB_TOKEN Permissions in Workflows). Its REST limit is 1,000 requests per hour per repository (15,000 for Enterprise Cloud resources). For cloud deployments, OIDC federation exchanges a short-lived GitHub-issued identity token for cloud credentials, removing stored cloud keys altogether; see the GitHub Actions OIDC Federation Hardening Guide. Use a GitHub App token inside a workflow only when the job must reach other repositories or organisation resources.

Worked scenarios

1. Release bot that tags and publishes across 40 repositories

The team runs it today on a lead engineer's classic PAT with repo and write:packages. Risk: the token reaches every repository the engineer can access in every organisation, and the bot breaks when they move team. Decision: a GitHub App owned by the organisation, installed on the 40 repositories, with Contents write and the minimum other permissions; private key in a sign-only vault; installation tokens minted per run. Package publishing: confirm whether the registry in use accepts GitHub App tokens and, if a classic PAT is still needed for that one step, isolate it on a machine account with only that scope and a short expiry.

2. Internal developer portal showing each engineer their pull requests

The portal must act as the signed-in user. Decision: a GitHub App using user access tokens, so the portal can do only what both the app permissions and the user allow, with refresh rather than long-lived tokens. An OAuth app would need repo scope and reach all of the user's repositories.

3. Security team script to inventory branch protection

Run weekly by one analyst. Decision: a GitHub App with read-only Administration and Metadata permissions installed on all repositories gives a stable, attributable identity. If the script is genuinely one-off, a fine-grained PAT with the organisation as resource owner, read-only permissions and a seven-day expiry, is acceptable.

4. Third-party code quality SaaS

The vendor offers OAuth only. Decision: an owner approves it under OAuth app access restrictions, knowing that an app authorised by an owner can reach anything visible to that owner's token in the organisation; prefer having a non-owner member request and use it where the workflow allows. Record scopes and owner, review quarterly, and ask the vendor for a GitHub App on its roadmap.

Decision checklist

  1. Does it run inside a single repository's workflow? Use GITHUB_TOKEN, plus OIDC for cloud access. Stop here if that covers it.
  2. Must actions be attributed to a person? Use a GitHub App with user access tokens; use an OAuth app only if you cannot change the product.
  3. Will it run for longer than a few weeks or outlive its author? Use a GitHub App installation.
  4. Is it a short, personal task? Fine-grained PAT, selected repositories, minimum permissions, expiry in days.
  5. Does it need a capability only classic PATs provide? Classic PAT on a machine account, minimum scopes, short expiry, written exception.
  6. Who holds the long-term secret? Private key in a vault, PAT in a secrets manager, OAuth tokens with the vendor: decide whose compromise you are accepting.

Small vs large organisations: a small team with a handful of repositories can begin by enforcing fine-grained PAT approval and expiry and moving its two or three busiest automations to GitHub Apps. Large enterprises should treat GitHub Apps as the standard, provide a shared internal service for minting installation tokens so teams do not each handle private keys, and restrict classic PATs at enterprise level.

Detection and measurement

GitHub audit log events carry token data: hashed_token (the SHA-256 hash of the token), programmatic_access_type and token_scopes. Searching hashed_token:"VALUE" finds activity from a specific PAT, OAuth token or GitHub App token, though Git events need an audit log export. Use this to separate machine and human activity and to scope a leak; see the GitHub Audit Log Detection Guide.

  • Alert on: new GitHub App installations or permission changes, new OAuth app approvals, fine-grained PAT approval requests for write permissions, and private key creation on organisation apps (T1098.001 Additional Cloud Credentials is the closest ATT&CK pattern for added credentials).
  • Hunt for: classic PAT use against organisation resources, tokens used from unexpected IP ranges, and app tokens touching repositories outside the app's normal set.
MetricDirection
Share of API activity from GitHub App and GITHUB_TOKEN identities versus PATsRising
Classic PATs with access to organisation resourcesZero, or a recorded exception list
Fine-grained PATs without expiry or above the lifetime capZero
GitHub Apps installed on all repositories without a recorded justificationFalling
Approved OAuth apps without an owner or review in 90 daysZero
Median time from leaked-token alert to revocationHours, not days

Common failure patterns

  • Personal token in CI: a maintainer's PAT added to workflow secrets to work around a permission problem, as in the SpotBugs token leak.
  • Migrating to an app but keeping the key in the repository: moving from PAT to GitHub App, then committing the private key, which never expires.
  • "All repositories" by default: installing apps or creating fine-grained PATs with all-repository access because selecting repositories was inconvenient.
  • Disabling OAuth restrictions: switching off restrictions to let one tool work, which removes owner approval for every OAuth app.
  • Leaver accounts kept alive: preserving a departed engineer's account because automation depends on their token.

Framework mapping

Control objectiveNIST SP 800-53 Rev. 5NIST CSF 2.0ISO/IEC 27001:2022 Annex A
Distinct, owned identities for automationIA-4, AC-2PR.AA-01A.5.16
Token and key lifetime, storage, rotationIA-5PR.AA-01A.5.17
Least privilege permissions and repository scopeAC-6PR.AA-05A.5.15, A.8.2
Approval and review of apps and tokensAC-2PR.AA-05A.5.18
Monitoring token activityAU-6DE.CM-03A.8.16

Leaked tokens are a common route into software supply chains (T1195.002 Compromise Software Supply Chain), which is why repository identity choice sits in supply chain programmes as well as identity governance.

Practitioner checklist

  • Inventory every GitHub App installation, OAuth app approval and PAT with organisation access, with an owner for each.
  • Make GitHub Apps the default for long-lived automation and integrations, owned by the organisation.
  • Store app private keys in a sign-only vault, keep a second key for rotation, and never commit them.
  • Restrict classic PAT access to organisation resources and record any exceptions.
  • Keep administrator approval for fine-grained PATs and set maximum lifetimes for both PAT types.
  • Keep OAuth app access restrictions on and review approved apps quarterly.
  • Set explicit permissions on GITHUB_TOKEN and use OIDC for cloud access from workflows.
  • Use hashed_token searches and token prefixes to attribute activity and scope leaks.

Standards and references

Related NHI Mgmt Group resources: GitHub Personal Access Tokens Security Guide · How to audit GitHub Apps and OAuth apps in an organisation · GitHub and GitHub Actions Security Guide · GitHub Actions OIDC Federation Hardening Guide · API Keys vs OAuth Tokens Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 13 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org