PuppyIP Resource Center
Developer Tools & Networking 6 min Published 2026-10-14

GitHub Apps: create repositories with less access and roll out expiring tokens

A GitHub App that only needs to create repositories can now request a dedicated permission instead of also receiving administration powers such as deletion and transfer. The October 13 update also lets developers try expiring user tokens one authorization at a time. Separate repository access, organization approval and token lifetimes before planning the rollout.

GitHub Apps Least privilege Repository permissions offline_access Token rotation

Service eligibility and regional restrictions

PuppyIP serves only compliant overseas businesses and their authorized personnel. Proxy services are not available in mainland China. The service may only be used for lawful business activities outside mainland China. Use of this service within mainland China is prohibited.

Hosting a proxy IP or server overseas does not change these restrictions. The service must not be provided to end users in mainland China through relaying, forwarding, sharing or resale. Before use, read the Terms of Service.

Key Takeaways

  • repository_creation:write covers repository creation. installation_repositories:write controls adding or removing a particular repository from an app installation; they solve different problems.
  • An organization administrator must still install the app. Repository administrators can add their repositories to an existing, approved organization installation, subject to organization restrictions and existing permission boundaries.
  • offline_access affects one user authorization, returning an expiring user token and a refresh token. It neither grants app permissions nor automatically changes future authorizations.
  • Expiring user tokens last eight hours and refresh tokens last six months. Refreshing invalidates both old tokens. Reenabling expiration globally does not make previously issued non-expiring tokens expire.

Create repositories without unnecessary administration powers

GitHub announced these GitHub Apps improvements on October 13, 2026. The two new repository-level fine-grained permissions also work with fine-grained personal access tokens. Least privilege means granting the capabilities a task needs rather than bundling every administrative operation for convenience.

repository_creation:write permits repository creation in the account where it is granted. Creation previously required the broader repository_administration:write permission, which also includes operations such as deletion and transfer. Automation that only creates repositories can now be designed around the narrower permission.

The app or user that creates the repository receives access to it. An app using the creation permission still needs an organization administrator to install it. This does not remove organization approval or establish that every existing automation step can drop administration access.

Start by listing the operations the workflow actually performs, then check the official repository creation APIs. If it also changes administrative settings, assess those operations separately. Successful creation alone does not establish that the whole workflow has sufficient permissions.

Adding a repository does not expand organization permissions

installation_repositories:write allows the caller to add or remove the repository on which it has permission from an installation in the organization. A user caller must also be an organization owner or an administrator of that repository. It does not let any member manage every repository in an organization.

The official Add and Remove endpoints now support GitHub App user access tokens, installation access tokens and fine-grained personal access tokens. The API documentation labels the required repository permission GitHub App installation repository access with write access, and requires an authenticated user to have repository admin access.

Both endpoints use /user/installations/{installation_id}/repositories/{repository_id}: PUT adds the repository and DELETE removes it. Removal also requires repository_selection to be selected. This endpoint cannot exclude one repository from an all-repositories installation or remove the last repository the app can access in the organization.

A related change lets repository administrators add their repositories to an existing organization installation once an organization owner has already approved the app’s organization access. Owners can still restrict this behavior. All organization-level permissions, repository administration and repository creation remain sensitive permission sets requiring owner approval.

offline_access changes token expiration, not app permissions

A GitHub App user access token acts on behalf of a user. An installation access token represents an app installation and serves a different purpose. The new offline_access support concerns user authorizations; do not mix the lifetimes or refresh flows of these two token types.

Even if an app has opted out of expiring user tokens globally, a developer can request offline_access for an individual user authorization. That authorization returns an expiring user access token and a refresh token. The choice does not automatically apply to every future session.

A GitHub App’s scope parameter does not dynamically request repository or organization permissions. The supported offline_access value selects the expiration mechanism. App permissions remain statically configured on the app registration, and a user token remains limited by both the app’s and the user’s permissions.

Treat the trial of expiring tokens and the reduction of repository permissions as separate checks. One limits how long the same token remains usable; the other limits what it can do. offline_access itself neither grants temporary privileges nor withdraws existing permissions.

Implement refresh before the eight-hour token expires

The official documentation gives expiring user tokens an eight-hour lifetime and refresh tokens a six-month lifetime. Exchanging a refresh token produces a new pair and invalidates both the old refresh token and the old user access token. The old refresh token cannot be reused indefinitely.

Refresh with a POST to GitHub’s /login/oauth/access_token path, using grant_type set to refresh_token, the app’s client_id and the current refresh_token. The client ID is different from the App ID. A client_secret is also required unless the user token was generated through the device flow.

Read access_token, expires_in, refresh_token and refresh_token_expires_in from the response, store the new pair securely and use the new values for subsequent requests. The official refresh documentation in Sources has the complete request and field definitions. Keep real tokens and client secrets out of support tickets.

As a rollout recommendation, use a controlled test authorization to check initial issuance, one refresh, invalidation of the old tokens and the client’s recovery path before widening the rollout. No authorization, token refresh or API mutation was performed for this guide; these are suggested checks rather than reported test results.

Do not mistake a global setting for migration of old tokens

For a hypothetical example, an app might have an interactive website and a long-running command-line client. Try offline_access first with a test client that already supports refresh, observe expiration and recovery, then schedule other clients. This illustrates a rollout sequence; it does not establish that any particular client already supports the flow.

New apps have user token expiration enabled unless the developer opts out. For an existing app, open GitHub Apps under Developer settings, edit the intended app and use Optional Features to change User-to-server token expiration. First confirm which app you administer.

Reenabling expiration globally does not make previously issued non-expiring user tokens expire. GitHub documents two ways to handle them: have users authenticate again, or delete the old tokens through the documented token revocation endpoint. Choose according to the migration plan; changing the setting alone does not complete rotation.

Track whether each client can refresh, still holds an old token and has a reauthentication recovery path. Those observations describe migration progress more accurately than the global toggle alone. No account, installation, permission or real credential was changed for this guide.

Check GHES 3.23 and 3.24 separately

The announcement assigns most improvements to GitHub Enterprise Server 3.24, with offline_access support arriving in 3.23. An older deployment cannot assume support from a GitHub.com announcement. These sources do not provide an exact deployment date or readiness status for every Server instance.

GitHub App credentials now have a dedicated Credentials tab. The announcement says it reserves space for upcoming workload federation credentials. Workload federation remains planned functionality; the new tab does not establish that federation has shipped.

These sources announce no new price, country eligibility list or mandatory migration deadline for every app. Plan around the actual GitHub product, organization policy and deployed version. Reader language or country does not by itself change the documented permission requirements.

Sources

Frequently Asked Questions

Does a 422 response from the removal endpoint mean the token format is wrong?

That status alone does not establish a token-format problem. The endpoint documents 422 when the app is installed on all repositories in the organization, or when removal would leave it with no accessible repository there. Check the installation selection and actual response. The documentation also lists 403 and 404; 204 indicates success.

Can an unused refresh token be renewed after its six-month lifetime?

GitHub’s documentation directs the user through the web application flow or device flow again to obtain a new user access token and refresh token. Do not treat an expired refresh token as valid, or assume that reauthentication grants extra app permissions.

Can an app now read the details of every private app?

No. The new Get an app access follows ownership boundaries: apps with the same owner in an organization can read one another’s details; internal apps can be read across organizations within the same enterprise; and an enterprise-owned app can read apps owned by organizations in that enterprise. Public apps were already readable by other apps. This does not make all private apps public.