DeepWiki

03 - Authentication-&-GitHub-Integration

Relevant source files

This page documents the authentication and GitHub integration architecture for godeep.wiki, which implements a dual authentication system:

  1. User OAuth tokens: Allow customers to view their connected repositories in the dashboard
  2. Installation access tokens: Enable the owner to access customer repositories for manual documentation generation

The system uses GitHub's OAuth 2.0 protocol combined with GitHub App installation to bridge payment to repository access. For payment processing details, see Payment Processing. For the admin panel that generates installation tokens, see Admin Panel. For the automation scripts that use these tokens, see Automation System.


The authentication system maintains clear separation between user capabilities and owner capabilities through distinct token types and authentication flows.

Dual Authentication Model

Key Architectural Principles:

AspectUser PathOwner Path
Authentication MethodOAuth 2.0 authorization code flowGitHub App JWT + installation token
Token StorageHTTP-only cookie (github_access_token)Not stored (generated on-demand)
Token Lifespan24 hours1 hour
Access ScopeUser's own repositoriesCustomer's shared repositories
Credentials UsedGITHUB_CLIENT_ID, GITHUB_CLIENT_SECRETGITHUB_APP_ID, GITHUB_PRIVATE_KEY
Primary Use CaseDashboard viewingRepository cloning and access

Sources: app/api/auth/github/route.ts L1-L44

app/api/auth/github/callback/route.ts L1-L149

CLAUDE.md L68-L80


The OAuth flow begins at /api/auth/github, which constructs the GitHub App installation URL with embedded state parameters for CSRF protection and payment correlation.

OAuth Initiation Route Handler

State Parameter Construction:

The state parameter encodes two critical pieces of information:

const stateData = {  uuid: crypto.randomUUID(),        // CSRF protection  sessionId: sessionId || null,     // Payment correlation}const state = Buffer.from(JSON.stringify(stateData)).toString('base64')

Implementation Details:

ComponentPurposeLocation
GITHUB_APP_SLUGIdentifies the GitHub App (e.g., godeepwiki-github-integration)app/api/auth/github/route.ts L5
github_oauth_state cookieStores state for verification in callbackapp/api/auth/github/route.ts L29-L34
session_id query parameterLinks payment to GitHub connectionapp/api/auth/github/route.ts L13
State encodingBase64-encoded JSON with UUID and session IDapp/api/auth/github/route.ts L16-L20

Cookie Configuration:

cookieStore.set("github_oauth_state", state, {  path: "/",  secure: process.env.NODE_ENV === "production",  // HTTPS only in production  httpOnly: true,                                  // Prevents XSS access  maxAge: 60 * 60,                                 // 1 hour expiry})

Sources: app/api/auth/github/route.ts L1-L44

CLAUDE.md L54-L66


When users click "Connect GitHub" on the success page, they are redirected to the GitHub App installation page where they select repositories and grant permissions.

GitHub App Installation Process

Repository Selection Security:

The system strongly recommends users select "Only select repositories" during installation, though this is a user choice, not an app-level configuration:

Selection OptionSecurity ImpactRecommendation
Only select repositoriesLimits access to explicitly chosen repos✅ Recommended
All repositoriesGrants access to all current and future repos⚠️ Not recommended

GitHub App Permissions:

The app requests minimal read-only permissions:

Permission TypeLevelPurpose
ContentsReadAccess repository files for cloning
MetadataReadAccess repository details (name, URL, etc.)
Email addresses (Account)ReadIdentify customer for email delivery

Critical OAuth Setting:

The GitHub App must have "Request user authorization (OAuth) during installation" enabled. This setting causes GitHub to return both installation_id AND code in the same callback, enabling the system to:

  1. Authenticate the user via OAuth (code)
  2. Link to the GitHub App installation (installation_id)
  3. Store the user token for dashboard access
  4. Log the installation for owner access

Sources: README.md L102-L149

github-app-description.md L1-L46

CLAUDE.md L186-L210


The callback handler at /api/auth/github/callback is the most complex component, responsible for state verification, token exchange, user data fetching, installation logging, and ntfy notification dispatch.

Callback Handler Flow

State Verification (CSRF Protection):

// Retrieve state from URL and cookieconst state = searchParams.get("state")const storedState = cookieStore.get("github_oauth_state")?.value// Verify matchif (!state || !storedState || state !== storedState) {  return new Response("Invalid state", { status: 400 })}

Session ID Extraction:

The callback decodes the state parameter to extract the Stripe session ID:

const stateData = JSON.parse(Buffer.from(state, 'base64').toString('utf-8'))stripeSessionId = stateData.sessionId  // Links to payment

Token Exchange Process:

StepEndpointPurpose
1. Exchange codePOST https://github.com/login/oauth/access_tokenConvert authorization code to access token
2. Fetch user dataGET https://api.github.com/userRetrieve username, email, user ID
3. Store tokenSet github_access_token cookieEnable dashboard access

Installation Logging:

When installation_id is present, the callback logs comprehensive details for owner correlation:

🎉 NEW GITHUB APP INSTALLATION
Stripe Session ID: cs_test_xxx
Installation ID: 12345678
GitHub Username: customer-username
GitHub Email: customer@example.com
GitHub User ID: 98765432
User Name: Customer Name
Setup Action: install
Timestamp: 2024-01-15T10:30:00.000Z

ntfy Notification Dispatch:

The callback sends a notification to ntfy.sh to trigger automation:

const message = `✅ GitHub Connected!🔑 Installation ID: ${installationId}📧 Customer: ${customerEmail}🔑 Match ID: ${sessionShort}  // Last 12 chars of session_id⏰ Time: ${timestamp}🤖 Automation will now:• Clone the repository• Create private repo in your accountCheck terminal for progress!`

User Token Cookie Configuration:

cookieStore.set("github_access_token", data.access_token, {  path: "/",  secure: process.env.NODE_ENV === "production",  httpOnly: true,        // XSS protection  maxAge: 60 * 60 * 24,  // 24 hours})

Sources: app/api/auth/github/callback/route.ts L1-L149

CLAUDE.md L54-L66


The system uses two distinct token types with different lifespans, purposes, and generation mechanisms.

Token Type Comparison

AspectUser OAuth TokenInstallation Access Token
PurposeDashboard access to user's own reposOwner access to customer's shared repos
GenerationOAuth authorization code flowGitHub App JWT authentication
Lifespan24 hours1 hour
Storagegithub_access_token cookieNot stored (ephemeral)
RenewalUser must re-authenticateGenerated on-demand via admin panel
Scoperead:user user:emailRepository-level (installation scoped)
Use Case/dashboard pageRepository cloning, GitHub API calls
Generated ByGitHub OAuth serverGitHub App API
Credentials RequiredGITHUB_CLIENT_ID, GITHUB_CLIENT_SECRETGITHUB_APP_ID, GITHUB_PRIVATE_KEY

User OAuth Token Lifecycle:

Installation Access Token Lifecycle:

Token Security Characteristics:

Security FeatureUser OAuth TokenInstallation Access Token
HTTP-Only✅ Yes (XSS protection)N/A (not stored in browser)
Secure Flag✅ Yes (production HTTPS)N/A
Short Lifespan⚠️ 24 hours✅ 1 hour (minimal exposure)
Revocable✅ User can revoke via GitHub✅ Auto-expires after 1 hour
Encrypted in Transit✅ HTTPS✅ HTTPS

Token Usage Examples:

User OAuth Token (Dashboard):

// In /dashboard pageconst cookieStore = await cookies()const token = cookieStore.get("github_access_token")?.valueconst response = await fetch("https://api.github.com/user/repos", {  headers: {    Authorization: `Bearer ${token}`,    Accept: "application/vnd.github.v3+json",  },})

Installation Access Token (Automation):

# Generated via /api/admin/generate-token# Used in automation scriptsgit clone https://oauth2:$INSTALLATION_TOKEN@github.com/customer/repo.git

Sources: app/api/auth/github/callback/route.ts L90-L96

CLAUDE.md L68-L80

README.md L395-L402


The system links Stripe payments to GitHub installations through the session_id parameter, which flows through the OAuth state mechanism and is logged for manual correlation.

Correlation Flow Diagram

State Parameter Encoding:

The session_id from Stripe is embedded in the OAuth state parameter:

StageData StructureFormat
Inputsession_id from URL parametercs_test_a1b2c3d4e5f6...
Encoding{uuid: "...", sessionId: "cs_test_a1b2c3d4e5f6..."}JSON object
State ParameterBase64-encoded JSONeyJ1dWlkIjoiLi4uIiwic2Vzc2lvbklkIjoiY3NfdGVzdF9hMWIyYzNkNGU1ZjYifQ==
Cookie StorageSame Base64 stringStored as github_oauth_state cookie

Correlation Logging:

The callback logs all correlation data to Vercel logs:

Stripe Session ID: cs_test_a1b2c3d4e5f6g7h8i9j0
Installation ID: 12345678
GitHub Username: customer-username
GitHub Email: customer@example.com
Timestamp: 2024-01-15T10:30:00.000Z

Match ID Mechanism:

The ntfy notification includes a "Match ID" (last 12 characters of session_id) for quick visual correlation:

const sessionShort = stripeSessionId ? stripeSessionId.slice(-12) : 'Not linked'// Example: cs_test_a1b2c3d4e5f6 → d4e5f6

Manual Correlation Workflow:

  1. Owner receives payment in Stripe Dashboard → notes session_id
  2. Owner checks Vercel logs for matching session_id
  3. Owner finds corresponding installation_id in logs
  4. Owner uses installation_id in /admin panel to generate access token
  5. Owner clones customer repository for manual documentation

Why Manual Correlation:

The system does not use a database to automatically link payments to installations. This design choice:

  • ✅ Simplifies architecture (no database required)
  • ✅ Reduces operational complexity
  • ✅ Works well for low-volume operations
  • ⚠️ Requires manual log inspection
  • ⚠️ Would be bottleneck at high scale

Sources: app/api/auth/github/route.ts L11-L24

app/api/auth/github/callback/route.ts L39-L50

app/api/auth/github/callback/route.ts L98-L121

CLAUDE.md L43-L65


The authentication system requires multiple environment variables for both OAuth and GitHub App authentication.

Required Environment Variables

VariablePurposeUsed ByExample
GITHUB_APP_SLUGGitHub App identifier in URLsOAuth initiationgodeepwiki-github-integration
GITHUB_CLIENT_IDOAuth client identifierOAuth flowIv1.a1b2c3d4e5f6g7h8
GITHUB_CLIENT_SECRETOAuth client secretToken exchangea1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
GITHUB_APP_IDGitHub App numeric IDInstallation token generation123456
GITHUB_PRIVATE_KEYGitHub App private key (PEM)JWT signing for installation tokens-----BEGIN RSA PRIVATE KEY-----\n...
GITHUB_WEBHOOK_SECRETWebhook signature verification/api/webhooks/githuba1b2c3d4e5f6...
NTFY_TOPICntfy.sh notification topicAutomation triggerklaudioz-codex-alerts-xxx

Obtaining GitHub App Credentials:

Step 1: App ID and Client ID

  • Navigate to: https://github.com/organizations/YOUR_ORG/settings/apps/YOUR_APP_SLUG
  • Found in "About" section

Step 2: Client Secret

  • Generate in "Client secrets" section
  • Copy immediately (shown only once)

Step 3: Private Key

  • Scroll to "Private keys" section
  • Click "Generate a private key"
  • Download .pem file
  • For Vercel: Use multiline string with actual line breaks
  • For local .env: Convert to base64 or use multiline string

Step 4: Webhook Secret

  • Generate: openssl rand -hex 32
  • Set in GitHub App webhook configuration
  • Store in GITHUB_WEBHOOK_SECRET

Environment Variable Usage Map:

Sources: README.md L73-L91

CLAUDE.md L88-L108

CLAUDE.md L211-L224


The authentication system implements multiple security layers to protect user credentials and prevent common attacks.

Security Features Summary

Attack VectorMitigation StrategyImplementation
CSRF (Cross-Site Request Forgery)OAuth state parameter with UUIDapp/api/auth/github/route.ts L17
XSS (Cross-Site Scripting)HTTP-only cookiesapp/api/auth/github/callback/route.ts L94
Man-in-the-MiddleHTTPS with Secure cookie flagapp/api/auth/github/callback/route.ts L93
Token TheftShort token lifespans (1 hour for installation tokens)Design decision
Unauthorized AccessRead-only repository permissionsGitHub App configuration
Session HijackingCookie-based state verificationapp/api/auth/github/callback/route.ts L32-L35
Replay AttacksState token deleted after useapp/api/auth/github/callback/route.ts L37

State Parameter Security Flow:

Cookie Security Configuration:

PropertyValueSecurity Benefit
httpOnlytruePrevents JavaScript access (XSS mitigation)
securetrue (production)Forces HTTPS transmission
maxAge3600 (1 hour for state), 86400 (24 hours for token)Limits exposure window
path/Restricts cookie scope
sameSiteDefault (Lax)CSRF protection for top-level navigation

Least Privilege Principle:

The GitHub App requests minimal permissions:

  • Contents: Read (not Write) → Cannot modify customer code
  • Metadata: Read → Basic repository information only
  • No admin permissions → Cannot change repository settings
  • User selects repositories → Access limited to chosen repos only

Token Exposure Mitigation:

Token TypeExposure RiskMitigation
User OAuth TokenStored in browser cookieHTTP-only, Secure flag, 24-hour expiry
Installation TokenNot stored1-hour expiry, generated on-demand, ephemeral
GitHub Client SecretServer-side onlyNever exposed to client
GitHub Private KeyServer-side onlyNever exposed to client

Known Security Limitations:

⚠️ Admin Password Exposure: NEXT_PUBLIC_ADMIN_PASSWORD is exposed to the client (due to NEXT_PUBLIC_ prefix). This is a simplified security model suitable for low-volume operations but not enterprise-grade. See Admin Authentication for details.

⚠️ No Rate Limiting: The system does not implement rate limiting on authentication endpoints, making it vulnerable to brute-force attacks on the admin panel.

Sources: app/api/auth/github/route.ts L29-L34

app/api/auth/github/callback/route.ts L91-L96

README.md L394-L406

CLAUDE.md L110-L116

Refresh this wiki

Last indexed: 23 November 2025 (922b35)

On this page

Ask Devin about godeep.wiki-jb

03 - Authentication-&-GitHub-Integration | DeepWiki | godeep.wiki