from typing import Dict, Any from .base import OAuthProvider class GitHubOAuthProvider(OAuthProvider): """GitHub OAuth provider implementation.""" @property def name(self) -> str: return 'github' @property def display_name(self) -> str: return 'GitHub' def get_client_config(self) -> Dict[str, Any]: """Return GitHub OAuth client configuration.""" return { 'access_token_url': 'https://github.com/login/oauth/access_token', 'authorize_url': 'https://github.com/login/oauth/authorize', 'api_base_url': 'https://api.github.com/', 'client_kwargs': { 'scope': 'user:email' } } def get_user_info(self, token: Dict[str, Any]) -> Dict[str, Any]: """Extract user information from GitHub OAuth token response.""" client = self.get_client() # Get user profile user_resp = client.get('user', token=token) user_data = user_resp.json() # Get user email (may be private) email = user_data.get('email') if not email: # If email is private, get from emails endpoint emails_resp = client.get('user/emails', token=token) emails = emails_resp.json() # Find primary email for email_obj in emails: if email_obj.get('primary', False): email = email_obj.get('email') break return { 'id': str(user_data.get('id')), 'email': email, 'name': user_data.get('name') or user_data.get('login'), 'picture': user_data.get('avatar_url') }