in src/github/operations/auth.ts [34:114]
export async function fetchGitHubTokenOwnerDetails(octokit: Octokits, tokenConfig: GitHubTokenConfig): Promise<TokenOwner> {
try {
// Default GITHUB_TOKEN has limited permissions and can't read user info
// Return well-known github-actions bot credentials to avoid unnecessary API call
if (tokenConfig.isDefaultToken()) {
console.log("Using default GITHUB_TOKEN - skipping token owner API call (insufficient permissions)");
return GITHUB_ACTIONS_BOT;
}
// For custom tokens (PATs, GitHub App tokens), fetch owner information from API
console.log("Using custom token - fetching token owner info");
try {
// Try to get user info (works for PATs)
const {data} = await octokit.rest.users.getAuthenticated();
console.log(`Token owner: ${data.login} (ID: ${data.id}, Type: ${data.type})`);
// Map GitHub API types to our internal type system
let type: TokenOwner["type"]
if (data.type === "Bot") {
type = "Bot";
} else {
type = "User";
}
return {
login: data.login,
id: data.id,
type,
};
} catch (userError: any) {
// If /user fails with "Resource not accessible", this is likely a GitHub App token
// GitHub App tokens can't access /user endpoint
if (userError?.status === 403 || userError?.message?.includes('Resource not accessible')) {
console.log("⚠️ /user endpoint not accessible - trying GraphQL viewer for GitHub App token");
try {
// Try GraphQL viewer query which works for GitHub App tokens
const graphqlResponse = await octokit.graphql<ViewerQueryResponse>(VIEWER_QUERY);
const { viewer } = graphqlResponse;
console.log(`GitHub App token owner (via GraphQL): ${viewer.login} (ID: ${viewer.databaseId})`);
return {
login: viewer.login,
id: viewer.databaseId,
type: "Bot",
};
} catch (graphqlError: any) {
// Both /user and GraphQL failed - can't authenticate
const graphqlErrorMessage = graphqlError?.message || String(graphqlError);
console.error("GraphQL viewer query failed:", graphqlErrorMessage);
throw new Error(
`Both REST API (/user) and GraphQL (viewer) queries failed.\n\n` +
`REST API error: ${userError?.message || userError}\n` +
`GraphQL error: ${graphqlErrorMessage}`
);
}
}
throw userError;
}
} catch (error) {
console.error("Failed to fetch token owner info:", error);
// Provide helpful error message based on error type
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(
`❌ Unable to authenticate with provided GitHub token.\n\n` +
`Possible causes:\n` +
`• Token is invalid or expired\n` +
`• Token lacks required permissions (needs 'read:user' or 'user' scope for PAT)\n` +
`• For GitHub App tokens: ensure proper installation permissions\n` +
`• GitHub API is unavailable\n` +
`• Rate limit exceeded\n\n` +
`Original error: ${errorMessage}`
);
}
}