Source code for aiohttp_tiny_mcp.oauth.github

"""GitHub.com OAuth App configuration and stable user identity lookup."""

from __future__ import annotations

from collections.abc import Sequence
from typing import Any

from aiohttp import ClientSession

from .provider import Identity, OAuthProvider, UpstreamAuthError, provider_json


async def github_identity(tokens: dict[str, Any], http: ClientSession) -> Identity:
    data = await provider_json(
        http,
        "GET",
        "https://api.github.com/user",
        headers={
            "Accept": "application/vnd.github+json",
            "Authorization": f"Bearer {tokens['access_token']}",
            "User-Agent": "aiohttp-tiny-mcp",
        },
    )
    if type(data.get("id")) is not int or data["id"] <= 0 or not isinstance(data.get("login"), str):
        raise UpstreamAuthError("GitHub returned no valid user identity.")
    return Identity(
        sub=str(data["id"]),
        provider="github",
        claims={key: data.get(key) for key in ("login", "name", "email")},
    )


[docs] def GitHub( client_id: str, client_secret: str, *, scopes: Sequence[str] = ("read:user",) ) -> OAuthProvider: """GitHub.com OAuth App sign-in. Register the server's callback URL in GitHub.""" if not client_secret: raise ValueError("the GitHub client secret is required") return OAuthProvider( name="GitHub", authorize_url="https://github.com/login/oauth/authorize", token_url="https://github.com/login/oauth/access_token", client_id=client_id, client_secret=client_secret, scopes=tuple(scopes), profile=github_identity, )
__all__ = ["GitHub"]