GitHub
github.com · Developer tools · for: AI agent reads repositories and issues and opens pull requests on the user's behalf.
Decide OAuth App vs GitHub App for your customers' security bar. If it's an OAuth App, register it under your company's GitHub org at github.com/settings/applications/new with HTTPS callback URLs (wildcard matching off) and keep 'Expire user access tokens' enabled.
Your path at a glance
Watch out for
- BlockerOrg restrictions hide private repos until an owner approveswhy & fix →
- Warning`repo` is all-or-nothingwhy & fix →
- WarningNew apps now get 8-hour tokens by defaultwhy & fix →
- WarningThe 11th token silently revokes an old onewhy & fix →
- WarningRate limit is the user's, shared with everything elsewhy & fix →
- InfoLegacy wildcard callback matching is on for older appswhy & fix →
- InfoUnknown client returns 404, not an OAuth errorwhy & fix →
Before you start
Steps
Configure OAuth
Test with your account
Launch to customers
Copy & paste
repopublic_reporead:orgread:useruser:emailworkflow- Developer console
- https://github.com/settings/developers
- OAuth docs
- https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
- Authorize URL
- https://github.com/login/oauth/authorize
- Token URL
- https://github.com/login/oauth/access_token
- Discovery
- https://github.com/.well-known/oauth-authorization-server/login/oauth
Show prompt
You are integrating 'Connect GitHub' (OAuth App, web application flow) into our app so an AI agent can read repos and issues and open PRs as the user.
The human has registered the OAuth App and put GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET in the environment (see .env template). Callback URL: ${APP_BASE_URL}/oauth/github/callback.
Implement:
1. GET /oauth/github/start: generate state and a PKCE code_verifier (43-128 chars) and store both in the session. Redirect to https://github.com/login/oauth/authorize?client_id=...&redirect_uri=...&scope=repo%20read:org%20read:user%20user:email&state=...&code_challenge=<base64url(sha256(verifier))>&code_challenge_method=S256.
2. GET /oauth/github/callback: verify state, then POST https://github.com/login/oauth/access_token with header Accept: application/json and body client_id, client_secret, code, redirect_uri, code_verifier. Store access_token, refresh_token, expires_in (8h) and refresh_token_expires_in (~6 months) encrypted per user. Handle responses without refresh_token, which happen if token expiry is disabled.
3. A token getter that refreshes when less than 10 minutes remain: POST the same token URL with grant_type=refresh_token, client_id, client_secret and refresh_token. Use a per-user mutex. Always persist the NEW refresh_token, since the old one is invalidated. On bad_refresh_token, mark the connection as needing re-auth.
4. A GitHub API client that sends Authorization: Bearer <token> and X-GitHub-Api-Version, reads X-OAuth-Scopes to detect missing scopes, and backs off on 403/429 using retry-after or x-ratelimit-reset.
5. After connecting, call GET /user/orgs and probe each org's private repos. Return a list of orgs that likely need owner approval, so the UI can show 'Ask your org owner to approve' with a link to https://github.com/settings/connections/applications/${GITHUB_CLIENT_ID}.
6. Tests: state mismatch, PKCE verifier missing, refresh race, 404 from the token endpoint (treat as a misconfigured client_id or secret).
Do not log tokens or the client secret. Do not run the OAuth flow more than once per user per environment, because GitHub caps live tokens at 10 per user/app/scope and revokes the oldest.Show bash
# GitHub OAuth App (Settings > Developer settings > OAuth apps)
GITHUB_CLIENT_ID=Ov23liXXXXXXXXXXXXXX
GITHUB_CLIENT_SECRET=replace-with-client-secret-from-github
APP_BASE_URL=https://app.example.com
GITHUB_REDIRECT_URI=${APP_BASE_URL}/oauth/github/callback
GITHUB_SCOPES="repo read:org read:user user:email"
GITHUB_AUTHORIZE_URL=https://github.com/login/oauth/authorize
GITHUB_TOKEN_URL=https://github.com/login/oauth/access_token
# Key used to encrypt stored tokens at rest
TOKEN_ENCRYPTION_KEY=replace-with-32-byte-random-key
Show yaml
application_name: Acme Agent homepage_url: https://app.example.com application_description: Acme Agent reads your repositories and issues and opens pull requests you ask for. callback_urls: # up to 10; turn wildcard matching OFF for each - http://127.0.0.1/oauth/github/callback # local dev (any port allowed for loopback) - https://staging.example.com/oauth/github/callback - https://app.example.com/oauth/github/callback enable_device_flow: false # true only for CLI/headless clients expire_user_access_tokens: true # default for new apps; requires refresh handling
Show typescript
const TOKEN_URL = "https://github.com/login/oauth/access_token";
export async function exchangeCode(code: string, verifier: string) {
const res = await fetch(TOKEN_URL, {
method: "POST",
headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: process.env.GITHUB_CLIENT_ID!,
client_secret: process.env.GITHUB_CLIENT_SECRET!,
code,
redirect_uri: process.env.GITHUB_REDIRECT_URI!,
code_verifier: verifier,
}),
});
if (res.status === 404) throw new Error("GitHub token endpoint 404: check client_id/secret for this environment");
const json = await res.json();
if (json.error) throw new Error(`${json.error}: ${json.error_description ?? ""}`);
return json as { access_token: string; refresh_token?: string; expires_in?: number; refresh_token_expires_in?: number; scope: string };
}
export async function refresh(refreshToken: string) {
const res = await fetch(TOKEN_URL, {
method: "POST",
headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: process.env.GITHUB_CLIENT_ID!,
client_secret: process.env.GITHUB_CLIENT_SECRET!,
grant_type: "refresh_token",
refresh_token: refreshToken,
}),
});
const json = await res.json();
if (json.error === "bad_refresh_token") throw new Error("REAUTH_REQUIRED");
if (json.error) throw new Error(json.error);
return json; // persist BOTH new access_token and new refresh_token
}
Why & details
The reasoning, evidence and sources behind everything above. Hover a badge to see its sources.
The full picture
Instant self-serve
GitHub OAuth Apps are instant and need no provider review, so you can have a working token in under 30 minutes, and new apps now get 8-hour tokens with refresh by default. The real friction is on the customer side: the only scope that covers private code, issues and PRs is `repo` (full read/write to every private repo the user can reach), and organisations that restrict OAuth Apps, as every new org does by default, hide their private repos until an org owner approves you, which is why GitHub recommends a GitHub App for this use case.
Any GitHub user or org admin can register an OAuth App and get a client ID and secret immediately. There is no app review, verification or user cap for OAuth Apps. A GitHub Marketplace listing is optional and only needed for discovery or paid plans. The friction is per customer: org owners must approve the app when OAuth app access restrictions are on, which is the default for new organisations.
Rating: Self-serve. You can ship the same day.
You have a GitHub account, can register an OAuth App under your account or an org you administer, and have a callback URL (http://127.0.0.1 loopback works for local dev). Your code must handle the refresh token, or you must untick 'Expire user access tokens'.
GitHub imposes no provider wait. Production means: an org-owned app with a clear name, homepage and logo; HTTPS callback URLs with wildcard matching off; refresh-token handling; and an in-product flow that tells users how to request org-owner approval. Each customer org that restricts OAuth Apps adds its own unpredictable approval wait, which is not counted here.
What affects your setup
- Customer admin consent
When an organisation has OAuth app access restrictions enabled, its members cannot authorize your OAuth App for org resources. They can only request approval, and an org owner grants it under Settings > Third-party access > OAuth app policy. Until then your token only sees the org's public resources. Restrictions are enabled by default for every newly created organisation. Orgs with SAML SSO also require the user to have an active SSO session at the moment they authorize.
- Token lifecycle gotchas
New OAuth Apps have 'Expire user access tokens' enabled by default (since the 2026-08-14 changelog). Access tokens last 8 hours, and refresh tokens last 6 months without use and are single-use: each refresh invalidates the old pair. If the option is off, tokens never expire but are revoked after one year without use. GitHub keeps at most 10 tokens per user/app/scope combination and silently revokes the oldest beyond that.
- Redirect URI rules
Up to 10 callback URLs per OAuth App (new as of the 2026-08-14 changelog; previously only one). Wildcard (subdirectory and subdomain) matching is now a per-URL toggle. Apps that had a single callback URL before 2026-08-03 have it switched on as a legacy default, and GitHub recommends turning it off. Loopback redirects (127.0.0.1 or ::1) may use any port. If you omit redirect_uri, GitHub uses the first configured callback URL.
- Marketplace listing optional
GitHub Marketplace is optional for distribution. Free listings only need to meet the general listing requirements. Paid plans require publisher verification of your organisation plus financial onboarding. Users can authorize your OAuth App without any listing.
Before you start — why each matters
- GitHub account or organisation to own the app — OAuth Apps can be owned by a personal account or by any org you administer (limit: 100 OAuth Apps per owner). Use an org owner so the app survives staff changes.
- Decision: OAuth App vs GitHub App — GitHub says 'GitHub Apps are preferred over OAuth apps': fine-grained permissions (issues, PRs and contents are separate), per-repository installation, 1-hour installation tokens, and rate limits that scale with the installation. OAuth Apps act only as the user, with coarse scopes. Pick an OAuth App only if you need user-wide access across every repo and org with minimal setup, or enterprise-level resources.
- Homepage URL and HTTPS callback URL — The homepage and app name are shown on the consent screen. Callback URLs must be ones you control; avoid wildcard matching unless you control every subdomain and path.
- Customer org owner approval — For each customer organisation that restricts OAuth Apps (the default for new orgs), an org owner must approve your app before the agent can see private org repos.
How well this guide is backed
Step details
For an agent that writes code and opens PRs, compare the blast radius. With an OAuth App, the `repo` scope reaches every private repo the user can access. With a GitHub App, the customer picks the repos and you request only Contents, Issues and Pull requests read/write. The rest of this guide covers the OAuth App path.
👤 Why you: A product/business judgement only you can make
🤖 What an agent can do: Summarise the trade-offs for your product (security review expectations of your customers, rate limits, token lifetimes) and draft a recommendation.
https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps ↗Under the owning org (or your profile), go to Settings > Developer settings > OAuth apps > New OAuth App. Enter the application name, homepage URL, description and callback URL(s).
👤 Why you: Needs your logged-in console session (2FA/CAPTCHA)
🤖 What an agent can do: Prepare the exact field values (name, homepage, description, list of callback URLs for local, staging and production) so the human only has to paste them.
https://github.com/settings/applications/new ↗Add up to 10 callback URLs, for example http://127.0.0.1/callback for local dev and https://app.example.com/oauth/github/callback for production. Turn wildcard matching off for each URL. Leave 'Expire user access tokens' ticked (the default) and implement refresh. Enable device flow only if you have a CLI or headless client.
👤 Why you: Needs your logged-in console session (2FA/CAPTCHA)
🤖 What an agent can do: Generate the callback URL list per environment and a checklist of the toggles to set.
https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#redirect-urls ↗Click 'Generate a new client secret' and copy it immediately into your secret manager. Never ship it to a browser or desktop client.
👤 Why you: Needs your logged-in console session (2FA/CAPTCHA)
🤖 What an agent can do: Write the .env template and secret-manager wiring. The human pastes the secret value.
https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/best-practices-for-creating-an-oauth-app ↗Redirect to /login/oauth/authorize with client_id, redirect_uri, scope='repo read:org read:user user:email', a random state, and code_challenge using S256. Exchange the code at /login/oauth/access_token with Accept: application/json, client_secret and code_verifier. Persist access_token, refresh_token and both expiry times. Refresh with grant_type=refresh_token before the 8 hours are up, and always store the new refresh token. On bad_refresh_token, re-run the flow.
🤖 What an agent can do: Write the authorize redirect, callback handler, token storage, refresh scheduler and a wrapper that reads the X-OAuth-Scopes response header to detect scopes the user removed.
https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#web-application-flow ↗Run the flow and approve on the consent screen. Then call GET /user and list your repos, create a branch and open a PR on a sandbox repo. Confirm the token response contains expires_in=28800 and a refresh_token, then force a refresh.
👤 Why you: Needs your logged-in console session (2FA/CAPTCHA)
🤖 What an agent can do: Write an end-to-end test script; the human only clicks 'Authorize' in the browser.
https://docs.github.com/en/rest/pulls/pulls#create-a-pull-request ↗After connection, list the user's orgs (GET /user/orgs). For each org where private repos are missing or return 404, tell the user to request approval: in their GitHub settings under Applications > Authorized OAuth Apps > your app, they click Request next to the org. Also offer re-authorization for SAML SSO orgs (active SSO session required).
🤖 What an agent can do: Implement org detection and the in-app explainer, with a deep link to https://github.com/settings/connections/applications/<CLIENT_ID>.
https://docs.github.com/en/organizations/managing-oauth-access-to-your-organizations-data/about-oauth-app-access-restrictions ↗Not required to onboard users. A free listing needs the general listing requirements. Paid plans require publisher verification and financial onboarding.
👤 Why you: A product/business judgement only you can make
🤖 What an agent can do: Draft listing copy and screenshots checklist if you decide to list.
https://docs.github.com/en/apps/github-marketplace/github-marketplace-overview/about-github-marketplace-for-apps ↗The org owner opens Organization Settings > Third-party Access > OAuth app policy, clicks Review next to your app, then Grant access. Until they do, the agent sees only public resources in that org, and webhooks from private repos are not delivered.
👤 Why you: Your customer's admin must act
🤖 What an agent can do: Draft a short email or help-center article the customer can forward to their org owner explaining what the app accesses and why.
https://docs.github.com/en/organizations/managing-oauth-access-to-your-organizations-data/approving-oauth-apps-for-your-organization ↗In Enterprise Cloud orgs that enforce SAML SSO, the user must have an active SSO session when authorizing, or the token won't reach that org. After an org newly enables SSO, users must re-authorize.
👤 Why you: Your customer's admin must act
🤖 What an agent can do: Detect the SSO gap (403 responses with an X-GitHub-SSO header, per GitHub's convention) and show the https://github.com/orgs/ORG/sso link before re-running OAuth.
https://docs.github.com/en/enterprise-cloud@latest/authentication/authenticating-with-single-sign-on/about-authentication-with-single-sign-on ↗
Gotchas explained
- BlockerOrg restrictions hide private repos until an owner approves
OAuth app access restrictions are on by default for newly created orgs. A user can connect successfully and still see none of their company's private repos. The API returns them as not found, and private-repo webhooks are not delivered.
Fix: Tell users at connect time which orgs are unapproved, provide a one-click 'request access' path, and give them a forwardable explanation for their org owner.
- Warning`repo` is all-or-nothing
No OAuth App scope gives read-only or per-repo access to private repositories. `repo` grants full read/write to every private repo the user can reach, across all their orgs. Security-conscious customers often reject this, and users can also untick scopes on the consent screen.
Fix: If customers care about least privilege, build a GitHub App (fine-grained, per-repo) instead. With an OAuth App, check the X-OAuth-Scopes header on every response and degrade gracefully.
- WarningNew apps now get 8-hour tokens by default
Since the 2026-08-14 changelog, 'Expire user access tokens' is enabled by default for new OAuth Apps. Older tutorials and libraries assume GitHub OAuth tokens never expire, so integrations break after 8 hours. Refresh tokens are single-use, so concurrent refreshes race and one fails with bad_refresh_token.
Fix: Implement refresh with a per-user lock and always persist the new refresh_token, or untick the option while you add support. Turning it on later doesn't expire existing tokens; users must sign in again.
- WarningThe 11th token silently revokes an old one
GitHub keeps at most 10 tokens per user/app/scope. If each agent worker, environment or retry loop runs its own OAuth flow for the same user, earlier tokens get revoked without warning. More than 10 new tokens per hour triggers a re-authorization prompt.
Fix: Store one token pair per user per environment centrally and share it across workers. Don't re-run OAuth on transient errors.
- WarningRate limit is the user's, shared with everything else
OAuth tokens draw on the user's 5,000 requests/hour (15,000 in Enterprise Cloud orgs), shared with their PATs and other apps. Secondary limits (900 points/min for REST, plus content-creation limits) can return 403 or 429 to an agent that reads many files or opens PRs in bursts.
Fix: Prefer GraphQL or bulk endpoints, cache repo contents, honour retry-after and x-ratelimit-reset, and space out write operations. A GitHub App installation token gets a separate, scaling budget.
- InfoLegacy wildcard callback matching is on for older apps
Apps that had a single callback URL before 2026-08-03 have wildcard matching on. Any subdomain or subpath of the callback then receives codes, which is an account-takeover risk if any of those paths serve user content.
Fix: Open the app settings and disable wildcard matching on each callback URL unless you truly need it.
- InfoUnknown client returns 404, not an OAuth error
With an invalid client_id, the token and device-code endpoints return HTTP 404 with {"error":"Not Found"} rather than a standard invalid_client error, and the authorize URL simply bounces to login. That makes typos in client_id or the wrong environment's credentials look like routing bugs.
Fix: Log the client_id prefix per environment and treat a 404 from /login/oauth/access_token as a credentials-configuration error.
Why each scope
| Scope | Why you need it | Tier | Evidence |
|---|---|---|---|
repo | Read code, issues and PRs in private repos, push branches and open pull requests. This is the only OAuth App scope that covers private repositories, and it grants full read/write to all of them, including settings such as collaborators and webhooks. | sensitive | |
public_repo | Alternative to `repo` if the agent only ever touches public repositories. Grants read/write to public repos. | basic | |
read:org | List the user's organisations and teams so the agent can show which orgs have or haven't approved the app. | basic | |
read:user | Read the user's profile to identify the connected account. | basic | |
user:email | Read the user's (possibly private) email addresses, for example to match commit authorship. | basic | |
workflow | Only needed if the agent's PRs add or modify files under .github/workflows. Without it, those pushes fail. | sensitive |
Reference facts
- Provider reviewNone for OAuth Apps. Register and ship. Marketplace listing is optional.
- Access token lifetime8 hours when 'Expire user access tokens' is on (the default for new apps since Aug 2026), with expires_in=28800. Otherwise the token never expires but is revoked after 1 year without use.
- Refresh tokensValid for 6 months without use and single-use (each refresh returns a new pair and kills the old one). You can't change scope on refresh. You can also opt in per sign-in by adding `offline_access` to the requested scopes.
- PKCESupported with S256 only (`plain` is rejected) and 'strongly recommended'. The client_secret is still required at the token endpoint for the web flow.
- Callback URLsUp to 10, each with its own wildcard-matching toggle. Loopback (127.0.0.1) may use any port.
- Device flowOff by default; enable it per app. No client_secret needed. Codes expire after 15 minutes. There is a limit of 50 code submissions per hour per app.
- API rate limit5,000 requests/hour per user (15,000 for GitHub Enterprise Cloud orgs), shared with that user's PATs and other apps. Secondary limit: 900 points/min for REST.
- Token capAt most 10 live tokens per user/app/scope combination. The 11th silently revokes the oldest unused one. More than 10 new tokens per hour triggers a re-authorization prompt.
- PKCE (from discovery document)Advertised methods: S256
- Scopes advertised in discoveryoffline_access
- Endpoints observed liveAuthorize: HTTP 302; redirects to github.com/login; → endpoint is live (client validation may happen after login) · Token: HTTP 404; error "Not Found"; → token endpoint is live and rejects a bogus code
What we verified — and what we couldn't
Live probes (no credentials)
- ✓discovery
https://github.com/.well-known/oauth-authorization-server/login/oauthHTTP 200; issuer https://github.com/login/oauth; authorize https://github.com/login/oauth/authorize; PKCE methods: S256[P1] - ✓authorize
https://github.com/login/oauth/authorizeHTTP 302; redirects to github.com/login; → endpoint is live (client validation may happen after login)[P2] - ✓token
https://github.com/login/oauth/access_tokenHTTP 404; error "Not Found"; → token endpoint is live and rejects a bogus code[P3] - ✓page
https://github.com/settings/developersHTTP 302; redirects to github.com/login[P4] - ✓page
https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-appsHTTP 200; title "Authorizing OAuth apps - GitHub Docs"[P5]
Open questions
- Does 'Expire user access tokens' default to on for every new OAuth App, including ones created via org settings and on GitHub Enterprise Server?The creation doc (S1) and the 2026-08-14 changelog (S5) say it is on by default for new apps. S5 says GHES gets these changes in 3.23, and S2 warns that offline_access may have no effect on older GHES versions. We did not create an app to observe it.To resolve: Create a throwaway OAuth App, complete one authorization, and check whether the token response includes expires_in and refresh_token.
- Are GitHub's OAuth discovery documents stable enough to depend on?Both metadata documents return valid JSON today (T3, T4), but S12 says they are in public preview, intended only for MCP clients, and subject to change. It also says GitHub does not implement OIDC or issue ID tokens, even though the OIDC document lists `openid`.To resolve: Hard-code the authorize and token URLs in production and use discovery only as a sanity check. Re-read S12 before relying on it.
- Can enterprise-level policies (for example Enterprise Managed Users or enterprise OAuth app policies) block an OAuth App outright, beyond org-level restrictions?We verified the org-level OAuth app policy and SAML SSO requirements only. We did not research enterprise-account policies or EMU behaviour for third-party OAuth Apps.To resolve: Read the GitHub Enterprise Cloud docs on enterprise policies for OAuth apps and EMU, or test with a design-partner customer on Enterprise Cloud.
- Is 5,000 requests/hour per user enough for your agent's workload?Agents that read whole repos or many issues can exhaust the shared per-user budget, and secondary limits are partly undisclosed (S9).To resolve: Instrument x-ratelimit-remaining during a realistic pilot. If you hit limits, evaluate GitHub App installation tokens, whose budget scales with repos and users.
Ask the provider
A ready-to-send message built from the open questions above.
- Send to
- No contact channel found — check https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps for developer support
- Subject
- OAuth integration questions — GitHub
Hi GitHub developer support team, We're building an integration where AI agent reads repositories and issues and opens pull requests on the user's behalf. Before we register an OAuth app and launch to customers, we couldn't find answers to the following in your documentation: 1. Does 'Expire user access tokens' default to on for every new OAuth App, including ones created via org settings and on GitHub Enterprise Server? (What we found: The creation doc (S1) and the 2026-08-14 changelog (S5) say it is on by default for new apps. S5 says GHES gets these changes in 3.23, and S2 warns that offline_access may have no effect on older GHES versions. We did not create an app to observe it.) 2. Are GitHub's OAuth discovery documents stable enough to depend on? (What we found: Both metadata documents return valid JSON today (T3, T4), but S12 says they are in public preview, intended only for MCP clients, and subject to change. It also says GitHub does not implement OIDC or issue ID tokens, even though the OIDC document lists `openid`.) 3. Can enterprise-level policies (for example Enterprise Managed Users or enterprise OAuth app policies) block an OAuth App outright, beyond org-level restrictions? (What we found: We verified the org-level OAuth app policy and SAML SSO requirements only. We did not research enterprise-account policies or EMU behaviour for third-party OAuth Apps.) 4. Is 5,000 requests/hour per user enough for your agent's workload? (What we found: Agents that read whole repos or many issues can exhaust the shared per-user budget, and secondary limits are partly undisclosed (S9).) Could you point us to the right documentation or process — including whether any review or approval is needed before customers outside our own account can connect, and the typical timeline? Thanks, [Your name] [Company · website]
Sources
- S1GitHub Docs: Creating an OAuth appofficial
- S2GitHub Docs: Authorizing OAuth appsofficial
- S3GitHub Docs: Scopes for OAuth appsofficial
- S4GitHub Docs: Differences between GitHub Apps and OAuth appsofficial
- S5GitHub Changelog (2026-08-14): Multiple redirect URIs and token refresh for OAuth appsofficial
- S6GitHub Docs: About OAuth app access restrictionsofficial
- S7GitHub Docs: Approving OAuth apps for your organizationofficial
- S8GitHub Enterprise Cloud Docs: About authentication with single sign-onofficial
- S9GitHub Docs: Rate limits for the REST APIofficial
- S10GitHub Docs: Token expiration and revocationofficial
- S11GitHub Docs: About GitHub Marketplace for appsofficial
- S12GitHub Docs: GitHub authentication discovery endpointsofficial
- S13GitHub Docs: Best practices for creating an OAuth appofficial
- S14GitHub Docs: Activating optional features for OAuth appsofficial
- S15GitHub Enterprise Cloud Docs: Authorizing OAuth apps (user guide, 'OAuth apps and organizations')official
- T1Probe: GET authorize with client_id=probe-invalid (302 to /login)probe
- T2Probe: POST token and device-code endpoints with bogus client (404 {"error":"Not Found"})probe
- T3Probe: RFC 8414 authorization server metadata (200, S256 only)probe
- T4Probe: OIDC discovery document (200, scopes openid/offline_access)probe
- P1Our probe: discovery check on github.comprobe
- P2Our probe: authorize check on github.comprobe
- P3Our probe: token check on github.comprobe
- P4Our probe: page check on github.comprobe
- P5Our probe: page check on docs.github.comprobe