Skip to content

Support for Authentication Schemes - Decouple user auth from GitHub API credentials#245

Closed
Copilot wants to merge 7 commits intomainfrom
copilot/fix-244
Closed

Support for Authentication Schemes - Decouple user auth from GitHub API credentials#245
Copilot wants to merge 7 commits intomainfrom
copilot/fix-244

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Aug 7, 2025

This PR implements a new authentication architecture that decouples user authentication from GitHub API credentials, addressing the security and flexibility concerns raised in the issue.

Problem

Previously, the application tightly coupled user authentication with GitHub API access:

  • Users needed GitHub API permissions (copilot, manage_billing, etc.) to view metrics
  • Only GitHub OAuth was supported for user authentication
  • User tokens were used directly for GitHub API calls

Solution

Implemented a flexible authentication scheme with three priority levels:

1. GitHub App Authentication (Recommended - New)

Uses GitHub App credentials for API calls while supporting multiple OAuth providers for user authentication:

# GitHub App handles API calls
NUXT_GITHUB_APP_ID=12345
NUXT_GITHUB_APP_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----..."
NUXT_GITHUB_APP_INSTALLATION_ID=67890

# Users authenticate via any OAuth provider
NUXT_OAUTH_GOOGLE_CLIENT_ID=your_google_client_id
NUXT_OAUTH_GOOGLE_CLIENT_SECRET=your_google_client_secret

# Optional access control
NUXT_AUTHORIZED_USERS=alice,bob,charlie

2. Personal Access Token (Legacy - Existing)

Continues to work as before for backward compatibility.

3. User OAuth Token (Deprecated - Existing)

Legacy GitHub OAuth mode continues to work but is now deprecated.

Key Features

🔐 Enhanced Security

  • Users no longer need GitHub API permissions
  • GitHub App uses minimal required permissions
  • Separate credentials for user auth vs API access

🌍 Multiple Identity Providers

  • Support for 20+ OAuth providers via nuxt-auth-utils
  • GitHub: /auth/github
  • Google: /auth/google
  • Microsoft: /auth/microsoft
  • And many more (Auth0, AWS Cognito, Discord, etc.)

👥 Flexible Authorization

  • Optional username-based access control
  • Comma-separated list in NUXT_AUTHORIZED_USERS
  • Case-insensitive matching
  • If not configured, all authenticated users are allowed

🔄 Backward Compatibility

  • All existing authentication methods continue to work
  • No breaking changes to current deployments
  • Gradual migration path available

Implementation Details

  • GitHub App Module: Handles JWT generation and installation token management with caching
  • Authorization Logic: Inline authorization checks in OAuth handlers for build compatibility
  • Enhanced Authentication Flow: Priority-based authentication selection
  • Comprehensive Documentation: Updated README with setup guides and migration instructions

Testing

  • ✅ All existing tests pass (85/85)
  • ✅ New authorization logic tested
  • ✅ Build compatibility verified
  • ✅ No breaking changes to existing functionality

Migration Guide

For existing deployments using NUXT_PUBLIC_USING_GITHUB_AUTH=true:

  1. Set up a GitHub App with required permissions
  2. Configure your preferred OAuth provider(s)
  3. Optionally set NUXT_AUTHORIZED_USERS for access control
  4. Remove NUXT_PUBLIC_USING_GITHUB_AUTH (defaults to false)

The new system provides better security, more flexibility, and easier user management while maintaining full backward compatibility.

Fixes #244.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.fontshare.com
    • Triggering command: node (vitest) (dns block)
    • Triggering command: node /home/REDACTED/work/copilot-metrics-viewer/copilot-metrics-viewer/node_modules/.bin/nuxt build (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)
  • api.fontsource.org
    • Triggering command: node (vitest) (dns block)
    • Triggering command: node /home/REDACTED/work/copilot-metrics-viewer/copilot-metrics-viewer/node_modules/.bin/nuxt build (dns block)
  • fonts.bunny.net
    • Triggering command: node (vitest) (dns block)
    • Triggering command: node /home/REDACTED/work/copilot-metrics-viewer/copilot-metrics-viewer/node_modules/.bin/nuxt build (dns block)
  • fonts.google.com
    • Triggering command: node (vitest) (dns block)
    • Triggering command: node /home/REDACTED/work/copilot-metrics-viewer/copilot-metrics-viewer/node_modules/.bin/nuxt build (dns block)
  • fonts.googleapis.com
    • Triggering command: node (vitest 2) (dns block)
    • Triggering command: node (vitest 1) (dns block)
    • Triggering command: node (vitest 3) (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Aug 7, 2025

@karpikpl 👋 This repository doesn't have Copilot instructions. With Copilot instructions, I can understand the repository better, work faster and produce higher quality PRs.

I can generate a .github/copilot-instructions.md file for you automatically. Click here to open a pre-filled issue and assign it to me. I'll write the instructions, and then tag you for review.

Copilot AI and others added 3 commits August 7, 2025 18:19
Co-authored-by: karpikpl <3539908+karpikpl@users.noreply.github.com>
…iple OAuth providers

Co-authored-by: karpikpl <3539908+karpikpl@users.noreply.github.com>
Co-authored-by: karpikpl <3539908+karpikpl@users.noreply.github.com>
Copilot AI changed the title [WIP] Support for Authentication Schemes Support for Authentication Schemes - Decouple user auth from GitHub API credentials Aug 7, 2025
Copilot AI requested a review from karpikpl August 7, 2025 18:37
@karpikpl karpikpl requested a review from Copilot August 10, 2025 02:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a new authentication architecture that decouples user authentication from GitHub API credentials, providing enhanced security and flexibility. The changes introduce GitHub App authentication as the preferred method while maintaining backward compatibility with existing authentication schemes.

Key Changes

  • New GitHub App authentication module with JWT generation and token caching
  • Support for multiple OAuth providers (Google, Microsoft) beyond GitHub
  • Optional user authorization system with configurable access control
  • Enhanced authentication priority system with three tiers of authentication methods

Reviewed Changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
server/modules/github-app-auth.ts Core GitHub App authentication module with JWT generation and token management
server/modules/authorization.ts User authorization logic for access control
server/modules/authentication.ts Enhanced authentication flow with priority-based scheme selection
server/routes/auth/github.get.ts Updated GitHub OAuth handler with authorization checks
server/routes/auth/google.get.ts New Google OAuth authentication handler
server/routes/auth/microsoft.get.ts New Microsoft OAuth authentication handler
nuxt.config.ts Configuration updates for new authentication schemes
package.json Added JWT library dependencies
README.md Comprehensive documentation for new authentication features
.env Environment variable templates for new authentication options
tests/github-app-auth.spec.ts Basic test placeholder for GitHub App authentication
tests/authorization.spec.ts Basic test placeholder for authorization module

Comment thread server/modules/authentication.ts Outdated
Comment thread server/routes/auth/github.get.ts Outdated
Comment thread server/modules/github-app-auth.ts Outdated
Comment thread server/modules/github-app-auth.ts Outdated
@karpikpl karpikpl marked this pull request as ready for review August 10, 2025 02:29
@karpikpl
Copy link
Copy Markdown
Collaborator

@copilot can you merge main into this branch?
Look at code review comments.
Make sure the new features are well tested with unit tests

Copilot AI and others added 2 commits August 10, 2025 02:38
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
…hentication features

Co-authored-by: karpikpl <3539908+karpikpl@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Aug 10, 2025

@copilot can you merge main into this branch?
Look at code review comments.
Make sure the new features are well tested with unit tests

Completed all requested items:

  1. Merged main into this branch - Successfully merged with latest changes including Teams tab redesign and dependency updates

  2. Addressed code review comments - Fixed all 4 review feedback items:

    • Removed confusing GitHub App auth condition
    • Simplified OAuth authorization checks
    • Extracted magic numbers to named constants (3600s, 300s)
  3. Added comprehensive unit tests - Significantly expanded test coverage for authentication features:

    • GitHub App Authentication: 5 tests covering JWT generation, token caching, configuration validation, and error handling
    • Authorization Logic: 9 tests covering user access control, case-insensitive matching, and edge cases
    • Authentication Flow: 6 tests covering priority-based method selection and token expiry logic
    • OAuth Integration: 18 tests covering authorization logic for GitHub, Google, and Microsoft OAuth providers

Test Results: All 140 tests now pass (improved from 87), with comprehensive coverage of the new authentication features including edge cases, error scenarios, and multi-provider OAuth support.

Commit: e5e734e

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.fontshare.com
    • Triggering command: node (vitest) (dns block)
  • api.fontsource.org
    • Triggering command: node (vitest) (dns block)
  • fonts.bunny.net
    • Triggering command: node (vitest) (dns block)
  • fonts.google.com
    • Triggering command: node (vitest) (dns block)
  • fonts.googleapis.com
    • Triggering command: node (vitest 1) (dns block)
    • Triggering command: node (vitest 3) (dns block)
    • Triggering command: node (vitest 2) (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@karpikpl karpikpl linked an issue Sep 3, 2025 that may be closed by this pull request
karpikpl added a commit that referenced this pull request Apr 24, 2026
Based on PR #245 but extended for this repo's full stack:
- PostgreSQL 16 service for historical mode / storage tests
- npm ci with Node LTS and cache
- Build step (required for preview server in Playwright)
- Unit tests (vitest, mocked data, no GitHub token needed)
- Playwright tests in mock mode (excluding @seed/@storage DB tests)

Agents working on DB features can use DATABASE_URL and
ENABLE_HISTORICAL_MODE to run the full storage pipeline locally.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
karpikpl added a commit that referenced this pull request Apr 24, 2026
* feat: multi-provider OAuth support (Google, Microsoft, Auth0, Keycloak)

- Add OAuth handlers for Google, Microsoft, Auth0, and Keycloak
- Add shared authorization utility with checkAuthorization() pure function
  and isUserAuthorized() Nuxt runtime config wrapper
- Authorization is checked BEFORE setUserSession() — unauthorized users
  never receive a session cookie
- Update GitHub OAuth handler with authorization check and login field
- Add NUXT_PUBLIC_REQUIRE_AUTH and NUXT_PUBLIC_AUTH_PROVIDERS env vars
- Add NUXT_AUTHORIZED_USERS and NUXT_AUTHORIZED_EMAIL_DOMAINS for
  optional application-level allowlisting (any provider)
- Keep NUXT_PUBLIC_USING_GITHUB_AUTH for backwards compatibility
- Add dynamic provider login buttons in MainComponent.vue
- Add PAT-mode shield icon button that opens dialog listing OAuth options
- Update nuxt.config.ts with runtimeConfig for all five providers
- Add 18 unit tests for authorization logic
- Update DEPLOYMENT.md: comprehensive Authentication section for all
  five providers (PAT, GitHub, Google, Microsoft, Auth0, Keycloak)
  with setup steps, env var reference table, and authorization docs
- Update README.md: deprecate NUXT_PUBLIC_USING_GITHUB_AUTH, document
  all new auth env vars with provider table

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: add GitHub App installation token support for PAT-less data access

- Add server/modules/github-app-auth.ts: signs RS256 JWTs with Node.js
  built-in Web Crypto (no external deps), exchanges for installation token,
  caches with 5-min refresh buffer before expiry
- Update authentication.ts: GitHub App is now priority 2 in the credential
  chain (mock → App token → PAT → user OAuth session token)
- Add githubAppId/githubAppPrivateKey/githubAppInstallationId to nuxt.config.ts
  runtimeConfig
- Document new vars in .env, README.md, and DEPLOYMENT.md
- DEPLOYMENT.md: new 'GitHub App Installation Token' section with step-by-step
  App creation, private key export, and env var setup

This enables Google/Microsoft/Auth0/Keycloak users to access the dashboard
without any user-owned PAT — the installation token is machine-issued and
scoped to exactly the required org permissions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: auto-discover GitHub App installation ID + org picker

- github-app-auth.ts: replace single global cache with per-installation Map;
  add paginated listAppInstallations() with 5-min TTL + thundering-herd dedup;
  getGitHubAppToken() resolves org from githubOrg/githubEnt query param →
  config → single-install auto-select; no installation ID config needed
- server/api/installations.get.ts: new auth-protected endpoint returning
  accessible orgs (Flow 2: App JWT; Flow 1: session.organizations)
- server/routes/auth/github.get.ts: redirect to /select-org when multiple
  installations found (was always redirecting to first org)
- app/pages/select-org.vue: blocking org picker page; single org auto-
  navigates, multiple shows Vuetify v-select + Continue button
- app/router.options.ts: add /select-org route
- nuxt.config.ts: remove githubAppInstallationId (no longer needed)
- .env, README.md, DEPLOYMENT.md: update docs to reflect auto-discovery

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(org-picker): filter installations to user's own orgs for GitHub OAuth

When a GitHub OAuth user logs in, call GET /user/installations with their
token so the org picker only shows orgs they have access to — not all 48
marketplace installations.

Priority order in /api/installations:
1. GitHub OAuth session token → /user/installations (user-filtered)
2. session.organizations (pre-populated at GitHub login)
3. App JWT → list ALL (fallback for non-GitHub OAuth / unauthenticated)

Also updated github.get.ts to always pre-populate session.organizations
(removed isPublicApp guard) so the picker page doesn't need a second
API call.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(org-picker): only filter installations per-user for public/marketplace apps

For private/internal apps (NUXT_PUBLIC_IS_PUBLIC_APP not set), listing all
installations via App JWT is correct — there are only a few known orgs.

Only marketplace/public apps need user-filtered results, since the App JWT
would otherwise return every org that ever installed the app from the marketplace.

When NUXT_PUBLIC_IS_PUBLIC_APP=true:
  1. GitHub OAuth token in session → /user/installations (live, user-scoped)
  2. session.organizations (pre-populated at GitHub login, used as fallback)

When NUXT_PUBLIC_IS_PUBLIC_APP=false (default):
  - App JWT lists all installations (private app, small known set)
  - Falls back to session.organizations for GitHub OAuth without App key

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(org-picker): show text input for public apps, dropdown for private apps

Public/marketplace apps (NUXT_PUBLIC_IS_PUBLIC_APP=true):
- App JWT lists ALL marketplace installs — useless for individual users
- Exception: GitHub OAuth login → /user/installations returns user-filtered list
- For all other login methods (Google, Microsoft, etc.): return empty list
  and show a manual text input so the user can type their org slug

Private/internal apps (default):
- App JWT lists a small, known set of installed orgs → show dropdown

This inverts the previous logic: the dropdown is for private apps where
the install list is meaningful; the text input is the fallback for public
apps where listing all installs would be misleading.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* security: enforce per-org authorization for public/marketplace apps

Without this check, any authenticated user (including Google/Microsoft
OAuth) could access Copilot metrics for ANY org that installed the
marketplace app by simply passing ?githubOrg=target-org.

Fix: when NUXT_PUBLIC_IS_PUBLIC_APP=true and no default org is
configured, the middleware verifies that the requested org is present
in session.organizations — a list populated at GitHub OAuth login via
GET /user/installations, which GitHub scopes to the user's own orgs.

Consequences:
- GitHub OAuth users: can only access orgs from their /user/installations
- Non-GitHub OAuth (Google, Microsoft, etc.): session.organizations is
  empty → 403 for all org-specific API requests. Users must sign in
  with GitHub to prove org membership, or an admin must set
  NUXT_PUBLIC_GITHUB_ORG to pin to a specific org.

The check is a no-op when NUXT_PUBLIC_IS_PUBLIC_APP is not set (private
internal apps) or when a default org is configured via env vars.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: block private key + public app misconfiguration, simplify installations auth

When NUXT_PUBLIC_IS_PUBLIC_APP=true and NUXT_GITHUB_APP_PRIVATE_KEY is set,
throw a 500 error immediately. The two modes are fundamentally incompatible:
a private key grants app-level access to ALL marketplace installations, while
public apps should use the user's own GitHub OAuth token (naturally user-scoped).

Changes:
- installations.get.ts: throw 500 misconfiguration error instead of silently
  using the JWT path; remove try/catch that was swallowing errors
- middleware/github.ts: remove session.organizations authorization check — no
  longer needed since the incompatible config combo is blocked at the source
- github.get.ts: remove session.organizations storage — not needed for security,
  kept inline installations fetch only for redirect logic (single org → direct,
  multiple → /select-org)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: guard select-org redirect behind auth check to prevent 401

When requireAuth/usingGithubAuth/isPublicApp is set and no session exists,
index.vue was unconditionally redirecting to /select-org before the user
logged in. /api/installations then returned 401.

Fix: only redirect to /select-org when auth is not required OR the user is
already logged in. When auth is required and there is no session, let
MainComponent render — it shows the login overlay, and after OAuth the
callback redirects to /select-org or directly to the org as before.

Also add a safety net in select-org.vue: if a 401 is returned (e.g. session
expired, direct URL navigation), redirect back to / so the login overlay
is displayed rather than showing a raw error message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: graceful fallback when App JWT fails, fix inflight cache bug

- installations.get.ts: catch JWT/network errors and return [] so the UI
  shows a manual text input instead of an error page
- github-app-auth.ts: move installationsInflight = null into finally block
  so a failed promise is never cached (previously caused permanent failure
  until server restart)
- github-app-auth.ts: add diagnostic log in buildAppJwt showing whether a
  numeric App ID or Client ID is used as JWT issuer, with a clearer error
  message when PEM signing fails

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: declare router in select-org.vue

useRouter() is auto-imported by Nuxt but must be called to get the
instance. Without this, all router.push/replace calls silently failed,
making the Continue button appear to do nothing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: GitHub OAuth scope and post-login redirect for non-member users

- Default GitHub OAuth scope to ['read:user'] so the authorize URL
  is never built with an empty scope= param (GitHub returns 404)
- Remove /user/installations call from github.get.ts onSuccess handler;
  redirect all users to /select-org instead, which already uses the
  App JWT (private app) or user token (public app) correctly via
  /api/installations — fixes 404 for GitHub users not in the org
- Use config.oauth?.github?.clientId as JWT issuer fallback so
  NUXT_GITHUB_APP_ID is not required when NUXT_OAUTH_GITHUB_CLIENT_ID
  is already set

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: isPublicApp triggers auth requirement and GitHub login overlay

NUXT_PUBLIC_IS_PUBLIC_APP=true now implies authentication is required,
consistent with NUXT_PUBLIC_USING_GITHUB_AUTH. Previously the server
middleware and MainComponent login overlay both missed isPublicApp in
their requireAuth checks, causing unauthenticated requests to fall
through and throw a generic 500 instead of redirecting to GitHub OAuth.

Changes:
- server/middleware/github.ts: add isPublicApp to requireAuth
- app/components/MainComponent.vue: add isPublicApp to isAuthRequired
  and to the activeProviders fallback (defaults to GitHub provider)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: NUXT_PUBLIC_AUTH_PROVIDERS being set implies auth required

Previously, setting NUXT_PUBLIC_AUTH_PROVIDERS=github alone was not
enough — you also needed NUXT_PUBLIC_REQUIRE_AUTH=true or the legacy
NUXT_PUBLIC_USING_GITHUB_AUTH=true to enforce authentication.

Now any non-empty AUTH_PROVIDERS value implies requireAuth, so the
minimum OAuth setup is:
  NUXT_PUBLIC_AUTH_PROVIDERS=github
  NUXT_OAUTH_GITHUB_CLIENT_ID=...
  NUXT_OAUTH_GITHUB_CLIENT_SECRET=...

NUXT_PUBLIC_USING_GITHUB_AUTH remains supported for backwards compat
but is no longer needed for new deployments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: simplify auth flags and public app org picker

- NUXT_PUBLIC_AUTH_PROVIDERS being set now implies authentication required;
  NUXT_PUBLIC_REQUIRE_AUTH is no longer needed and hidden from docs
- NUXT_PUBLIC_USING_GITHUB_AUTH removed from docs (kept in code for compat)
- NUXT_PUBLIC_IS_PUBLIC_APP: org picker always shows text input (no server-
  side /user/installations enumeration); user types org slug directly
- .env.example: cleaned up auth section, one comment explains AUTH_PROVIDERS
- README + DEPLOYMENT: removed REQUIRE_AUTH and USING_GITHUB_AUTH entries,
  stripped REQUIRE_AUTH=true from all provider config examples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add GitHub App installation callback welcome page

Adds app/pages/callback.vue — a simple informational page for the
GitHub App post-installation Setup URL. GitHub redirects here after
install/update with ?setup_action=install|update (code and
installation_id are ignored since there's no server-side storage).

The page:
- Shows 'Thanks for Installing!' or 'App Updated' based on setup_action
- Informs users about the self-hosted PostgreSQL mode for historical
  metrics and per-user analytics
- Links to DEPLOYMENT.md for setup instructions
- Provides a 'Go to Dashboard' button back to the app

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Rename callback page to install (/callback → /install)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Register /install route in router.options.ts

The router.options.ts manually overrides all routes, so new pages
must be explicitly added here. Also moves install.vue to
install/index.vue directory structure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add Copilot metrics access permission note to install page

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Refactor public app org detection and add transparency messaging

- Move /user/installations call into onSuccess in github.get.ts to match
  main branch pattern; stores organizations in session; redirects to org
  directly for single-org users or /select-org for multiple/zero
- Simplify select-org.vue to read organizations from session (no API call
  on mount); preserve multi-org picker vs main's blind [0] pick
- Simplify installations.get.ts to return session.organizations for
  isPublicApp (no redundant GitHub API call)
- Remove old flat install.vue; add install/index.vue with privacy banner
- Add transparency alert to select-org.vue explaining app uses user's own
  credentials and does not store/process Copilot data
- Update MARKETPLACE.md: clarify listed org permissions are for
  self-hosted only; hosted app requests no org-level permissions
- Update TRANSPARENCY_DISCLOSURES.md: split Data Handling and Permissions
  sections into hosted vs self-hosted modes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix docs: hosted app still requires Copilot permissions on GitHub App

GitHub App user-to-server (ghu_) tokens are constrained by the App's own
permission settings — removing Copilot Metrics/Seat Management from the
App causes 403s even when the user has access. Document this clearly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add 'how it works' section to post-install page

Explains the GitHub App permission intersection model:
- App permissions are a hard ceiling
- User's own GitHub permissions still apply
- Neither party can escalate privileges unilaterally

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Replace raw red error div with v-alert and add 403 message

- Replace .error-message div with Vuetify v-alert (tonal, closable)
- Add 403 case with human-readable explanation about Copilot metrics
  access permissions instead of exposing raw GitHub API URLs
- Keep default fallback for unhandled status codes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add copilot-setup-steps.yml for Copilot coding agent

Based on PR #245 but extended for this repo's full stack:
- PostgreSQL 16 service for historical mode / storage tests
- npm ci with Node LTS and cache
- Build step (required for preview server in Playwright)
- Unit tests (vitest, mocked data, no GitHub token needed)
- Playwright tests in mock mode (excluding @seed/@storage DB tests)

Agents working on DB features can use DATABASE_URL and
ENABLE_HISTORICAL_MODE to run the full storage pipeline locally.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix CodeQL alerts: remove sensitive data from logs, add JWT signing suppression, add missing semicolon

- Remove appId from console.log in buildAppJwt (clear-text logging of OAuth data)
- Add codeql[js/insufficient-password-hash] suppression on sign.update(): this is
  RS256 JWT signing for GitHub App auth, not password storage
- Add missing semicolon in authentication.ts (code quality)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix CodeQL: require NUXT_GITHUB_APP_ID explicitly, remove OAuth clientId fallback

CodeQL was flagging config.oauth.github.clientId as a sensitive OAuth taint
source flowing through the JWT signing path (sign.update). The clientId fallback
was a convenience shortcut but is semantically wrong — the GitHub App ID (numeric)
and OAuth Client ID are different identifiers. Requiring NUXT_GITHUB_APP_ID to be
set explicitly breaks the taint chain and is cleaner: users setting up App auth
should set this env var regardless.

- Remove config.oauth?.github?.clientId fallback from authentication.ts
- Remove same fallback from github-app-auth.ts getGitHubAppToken
- Remove now-unnecessary codeql suppression comment
- Update error messages to reference NUXT_GITHUB_APP_ID only

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: trigger CodeQL re-evaluation after alert fixes

Previous CodeQL check fired before the fix commit's SARIF was uploaded.
Branch now has zero open code scanning alerts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove OAuth clientId fallback from installations endpoint

The config.oauth?.github?.clientId fallback in installations.get.ts
created a CodeQL taint path:
  oauth.clientId → appId → listAppInstallations → buildAppJwt
  → signJWT → sign.update() → flagged as insufficient password hash

Users who need to list App installations must set NUXT_GITHUB_APP_ID
explicitly. This matches the requirement in authentication.ts and
github-app-auth.ts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: bump version to 3.6.0

New features in this release:
- GitHub App installation token authentication
- Multi-provider OAuth (GitHub, Azure AD, Okta, Google)
- Public/marketplace app mode with org auto-detection
- GitHub App install callback/welcome page
- Improved error page with actionable 403 messaging

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: redirect /callback to /install for GitHub App compat

GitHub App registrations with Callback URL or Setup URL pointing to
/callback (old route name) now redirect seamlessly to /install, passing
through all query params (code, installation_id, setup_action).

Avoids requiring changes to the GitHub App settings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@karpikpl karpikpl closed this Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for Authentication Schemes Only Organization Owner can view Copilot Metrics

3 participants