Create auth.py
Browse files
    	
        auth.py
    ADDED
    
    | @@ -0,0 +1,71 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            from typing import Optional, Dict
         | 
| 3 | 
            +
            from authlib.integrations.requests_client import OAuth2Session
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class OAuthManager:
         | 
| 6 | 
            +
                """
         | 
| 7 | 
            +
                Manages OAuth2 flows for third-party services: GitHub, Google Drive, Slack.
         | 
| 8 | 
            +
                """
         | 
| 9 | 
            +
                def __init__(self):
         | 
| 10 | 
            +
                    self.providers: Dict[str, Dict] = {
         | 
| 11 | 
            +
                        'github': {
         | 
| 12 | 
            +
                            'client_id': os.getenv('GITHUB_CLIENT_ID'),
         | 
| 13 | 
            +
                            'client_secret': os.getenv('GITHUB_CLIENT_SECRET'),
         | 
| 14 | 
            +
                            'authorize_url': 'https://github.com/login/oauth/authorize',
         | 
| 15 | 
            +
                            'token_url': 'https://github.com/login/oauth/access_token',
         | 
| 16 | 
            +
                            'scope': 'repo read:org'
         | 
| 17 | 
            +
                        },
         | 
| 18 | 
            +
                        'google': {
         | 
| 19 | 
            +
                            'client_id': os.getenv('GOOGLE_CLIENT_ID'),
         | 
| 20 | 
            +
                            'client_secret': os.getenv('GOOGLE_CLIENT_SECRET'),
         | 
| 21 | 
            +
                            'authorize_url': 'https://accounts.google.com/o/oauth2/auth',
         | 
| 22 | 
            +
                            'token_url': 'https://oauth2.googleapis.com/token',
         | 
| 23 | 
            +
                            'scope': 'openid email profile https://www.googleapis.com/auth/drive.readonly'
         | 
| 24 | 
            +
                        },
         | 
| 25 | 
            +
                        'slack': {
         | 
| 26 | 
            +
                            'client_id': os.getenv('SLACK_CLIENT_ID'),
         | 
| 27 | 
            +
                            'client_secret': os.getenv('SLACK_CLIENT_SECRET'),
         | 
| 28 | 
            +
                            'authorize_url': 'https://slack.com/oauth/v2/authorize',
         | 
| 29 | 
            +
                            'token_url': 'https://slack.com/api/oauth.v2.access',
         | 
| 30 | 
            +
                            'scope': 'channels:read chat:write'
         | 
| 31 | 
            +
                        }
         | 
| 32 | 
            +
                    }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def _create_session(self, provider: str, redirect_uri: str) -> OAuth2Session:
         | 
| 35 | 
            +
                    cfg = self.providers.get(provider)
         | 
| 36 | 
            +
                    if not cfg or not cfg['client_id'] or not cfg['client_secret']:
         | 
| 37 | 
            +
                        raise RuntimeError(f"OAuth credentials for '{provider}' are not configured.")
         | 
| 38 | 
            +
                    return OAuth2Session(
         | 
| 39 | 
            +
                        cfg['client_id'],
         | 
| 40 | 
            +
                        cfg['client_secret'],
         | 
| 41 | 
            +
                        scope=cfg['scope'],
         | 
| 42 | 
            +
                        redirect_uri=redirect_uri
         | 
| 43 | 
            +
                    )
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def get_authorization_url(self, provider: str, redirect_uri: str, state: Optional[str] = None) -> (str, str):
         | 
| 46 | 
            +
                    """
         | 
| 47 | 
            +
                    Generate the OAuth2 authorization URL and state.
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    Returns:
         | 
| 50 | 
            +
                        (authorization_url, state)
         | 
| 51 | 
            +
                    """
         | 
| 52 | 
            +
                    session = self._create_session(provider, redirect_uri)
         | 
| 53 | 
            +
                    url, state = session.create_authorization_url(self.providers[provider]['authorize_url'], state=state)
         | 
| 54 | 
            +
                    return url, state
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                def fetch_token(self, provider: str, redirect_uri: str, authorization_response: str) -> Dict:
         | 
| 57 | 
            +
                    """
         | 
| 58 | 
            +
                    Exchange the authorization response for an access token.
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    Returns:
         | 
| 61 | 
            +
                        Token dict containing access_token, refresh_token, expires_in, etc.
         | 
| 62 | 
            +
                    """
         | 
| 63 | 
            +
                    session = self._create_session(provider, redirect_uri)
         | 
| 64 | 
            +
                    token = session.fetch_token(
         | 
| 65 | 
            +
                        self.providers[provider]['token_url'],
         | 
| 66 | 
            +
                        authorization_response=authorization_response
         | 
| 67 | 
            +
                    )
         | 
| 68 | 
            +
                    return token
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            # Instantiate a global manager
         | 
| 71 | 
            +
            oauth_manager = OAuthManager()
         | 
