Retrieve GitHub user profiles and check OAuth permissions for the authenticated user.
GET /api/user-profile
Fetch a GitHub user’s public profile information.
Response
URL to user’s avatar image
URL to user’s GitHub profile
User’s Twitter/X username
Number of users following
Number of public repositories
User type (“User” or “Organization”)
Account creation timestamp (ISO 8601)
const username = 'octocat';
const response = await fetch(`/api/user-profile?username=${username}`);
const profile = await response.json();
console.log(profile);
/*
{
login: "octocat",
name: "The Octocat",
avatar_url: "https://avatars.githubusercontent.com/u/583231",
html_url: "https://github.com/octocat",
bio: "GitHub mascot",
company: "@github",
location: "San Francisco",
blog: "https://github.blog",
twitter_username: "github",
followers: 9876,
following: 12,
public_repos: 8,
type: "User",
created_at: "2011-01-25T18:44:36Z"
}
*/
Cache Control
The user profile endpoint returns private cache headers to prevent authenticated responses from being shared:
Cache-Control: private, no-store
This ensures that:
- Responses are not cached by shared/public caches
- Each user gets their own authenticated view
- No sensitive data leaks between users
GET /api/user-scopes
Get OAuth scopes granted for the authenticated user’s GitHub account.
Response
Array of granted OAuth scope strings
const response = await fetch('/api/user-scopes');
const data = await response.json();
console.log(data.scopes);
/*
[
"repo",
"user",
"read:org",
"workflow"
]
*/
Common GitHub OAuth Scopes
Repository Scopes
repo - Full control of private repositories
repo:status - Access commit status
repo_deployment - Access deployment status
public_repo - Access public repositories
repo:invite - Access repository invitations
security_events - Read and write security events
User Scopes
user - Full user profile access (read/write)
read:user - Read user profile data
user:email - Access user email addresses
user:follow - Follow/unfollow users
Organization Scopes
admin:org - Full organization control
write:org - Write organization data
read:org - Read organization data
Other Scopes
gist - Create gists
notifications - Access notifications
workflow - Update GitHub Actions workflows
delete_repo - Delete repositories
Usage Examples
Display User Card
async function renderUserCard(username: string) {
try {
const profile = await fetch(`/api/user-profile?username=${username}`)
.then(r => r.json());
return `
<div class="user-card">
<img src="${profile.avatar_url}" alt="${profile.name}" />
<h2>${profile.name || profile.login}</h2>
<p class="username">@${profile.login}</p>
${profile.bio ? `<p class="bio">${profile.bio}</p>` : ''}
<div class="stats">
<span>${profile.followers} followers</span>
<span>${profile.public_repos} repos</span>
</div>
${profile.company ? `<p>📍 ${profile.company}</p>` : ''}
${profile.location ? `<p>🌍 ${profile.location}</p>` : ''}
</div>
`;
} catch (error) {
console.error('Failed to fetch user:', error);
return '<p>User not found</p>';
}
}
Compare User Stats
async function compareUsers(username1: string, username2: string) {
const [user1, user2] = await Promise.all([
fetch(`/api/user-profile?username=${username1}`).then(r => r.json()),
fetch(`/api/user-profile?username=${username2}`).then(r => r.json())
]);
return {
followers: {
[username1]: user1.followers,
[username2]: user2.followers,
leader: user1.followers > user2.followers ? username1 : username2
},
repos: {
[username1]: user1.public_repos,
[username2]: user2.public_repos,
leader: user1.public_repos > user2.public_repos ? username1 : username2
}
};
}
Permission Gate
async function requireScopes(requiredScopes: string[]) {
const { scopes } = await fetch('/api/user-scopes').then(r => r.json());
const missingScopes = requiredScopes.filter(scope => !scopes.includes(scope));
if (missingScopes.length > 0) {
throw new Error(
`Missing required permissions: ${missingScopes.join(', ')}. ` +
`Please re-authenticate with additional scopes.`
);
}
return true;
}
// Usage
try {
await requireScopes(['repo', 'workflow']);
// Proceed with GitHub Actions workflow updates
} catch (error) {
console.error(error.message);
// Show re-authentication prompt
}
Conditional UI Rendering
async function renderNavigation() {
const { scopes } = await fetch('/api/user-scopes').then(r => r.json());
const navItems = [
{ label: 'Repositories', path: '/repos', scope: 'repo' },
{ label: 'Pull Requests', path: '/pulls', scope: 'repo' },
{ label: 'Actions', path: '/actions', scope: 'workflow' },
{ label: 'Organizations', path: '/orgs', scope: 'read:org' },
{ label: 'Gists', path: '/gists', scope: 'gist' }
];
return navItems
.filter(item => !item.scope || scopes.includes(item.scope))
.map(item => `<a href="${item.path}">${item.label}</a>`);
}