Imported from mxyxyz9/Tabs-ide (
tabs-code-main/extensions/copilot/src/platform/authentication/common/AGENTS.md). Install upstream withnpx skills add mxyxyz9/Tabs-ide --skill common. Copyright stays with the author.
Authentication Service Usage Guide
Overview
IAuthenticationService manages GitHub and Copilot authentication. It provides GitHub sessions (OAuth tokens) and Copilot tokens (CAPI tokens).
Choosing a Session Kind
getGitHubSession requires a kind parameter. Choose thoughtfully:
'any'— Accepts whatever GitHub session is available, even one with minimal scopes (e.g., justuser:email). Use this when you only need basic access and don't require repo or write permissions.'permissive'— Requires a session with broader scopes (read:user,user:email,repo,workflow). Use when you need private repo access or write permissions.
The Three Overloads of getGitHubSession
1. Interactive — prompt user to sign in
Returns AuthenticationSession (never undefined). Throws if the user cancels.
Requires createIfNone with a StrictAuthenticationPresentationOptions containing a localized detail string explaining why auth is needed:
const session = await authService.getGitHubSession('any', {
createIfNone: { detail: l10n.t('Sign in to GitHub to use feature X.') }
});
2. Interactive — force a new session
Same as above but forces re-authentication even if a session exists. Use when the current token has lost authorization:
const session = await authService.getGitHubSession('any', {
forceNewSession: { detail: l10n.t('Sign in again to restore access.') }
});
3. Silent — no user prompt
Returns AuthenticationSession | undefined. Never shows UI. Use when auth is optional:
const session = await authService.getGitHubSession('any', { silent: true });
if (!session) {
// No session available, handle gracefully
}
Important Constraints
createIfNoneandforceNewSessiondo NOT acceptboolean. You must pass aStrictAuthenticationPresentationOptionswith a requireddetailstring. Passingtrue,false, or{}will not compile.- The
detailstring must be localized usingl10n.t('...'). - The silent overload's options type is
Omit<AuthenticationGetSessionOptions, 'createIfNone' | 'forceNewSession'>— you cannot sneak a booleancreateIfNonethrough it.
Synchronous Cache Properties
For non-blocking checks (no network, no UI), use the cached properties:
authService.anyGitHubSession— cached'any'session orundefinedauthService.permissiveGitHubSession— cached'permissive'session orundefinedauthService.copilotToken— cached Copilot token (without the raw token string) orundefined
React to onDidAuthenticationChange for identity changes (sign in/out, account switch).
React to onDidCopilotTokenChange for token-level updates (quota, feature flags, routine ~20-minute refreshes).
Copilot Tokens
Most callers just need a valid CAPI token. getCopilotToken() handles refresh automatically:
const token = await authService.getCopilotToken();
Minimal Mode
When authService.isMinimalMode is true, the service will not fetch permissive tokens:
- Interactive
'permissive'calls throwMinimalModeError - Silent
'permissive'calls returnundefined
Auth State Flows
There are three states a user can be in:
-
Not signed in — No
'any'session exists. The user has no GitHub session at all. An interactivecreateIfNonecall will show VS Code's built-in sign-in dialog. -
Signed in from VS Code — The user explicitly signed in through VS Code (e.g., via Accounts menu or a
createIfNoneprompt). In this case, VS Code automatically acquires the permissive token since it requests the broader scopes upfront. Both'any'and'permissive'sessions are available. -
Signed in passively (e.g., via Settings Sync) — The user is signed into GitHub through a passive mechanism that only grants minimal scopes. Copilot Chat works with the
'any'token, but no'permissive'token is available. A'permissive'call withcreateIfNonewill prompt the user to grant additional permissions.