MemPrepMate / src /services /auth_service.py
Christian Kniep
fix: Add jwks_uri to HuggingFace OAuth config
b211df8
"""
HuggingFace OAuth authentication service.
Feature: 012-profile-contact-ui
"""
import os
from authlib.integrations.flask_client import OAuth
class AuthService:
"""HuggingFace OAuth service."""
def __init__(self, app=None):
self.oauth = OAuth()
self.hf = None
if app:
self.init_app(app)
def init_app(self, app):
"""Initialize OAuth with Flask app."""
self.oauth.init_app(app)
# Get OAuth URLs from environment (allows mock OAuth for local dev)
authorization_url = os.getenv(
"HF_AUTHORIZATION_URL",
"https://huggingface.co/oauth/authorize"
)
token_url = os.getenv(
"HF_TOKEN_URL",
"https://huggingface.co/oauth/token"
)
userinfo_url = os.getenv(
"HF_USERINFO_URL",
"https://huggingface.co/oauth/userinfo"
)
jwks_uri = os.getenv(
"HF_JWKS_URI",
"https://huggingface.co/oauth/jwks"
)
# Register OAuth provider (HuggingFace or mock)
# HF Spaces provides OAUTH_CLIENT_ID/SECRET when hf_oauth: true
# Local dev uses HF_CLIENT_ID/SECRET
client_id = os.getenv("OAUTH_CLIENT_ID") or os.getenv("HF_CLIENT_ID")
client_secret = os.getenv("OAUTH_CLIENT_SECRET") or os.getenv("HF_CLIENT_SECRET")
self.hf = self.oauth.register(
name="huggingface",
client_id=client_id,
client_secret=client_secret,
authorize_url=authorization_url,
access_token_url=token_url,
userinfo_endpoint=userinfo_url,
jwks_uri=jwks_uri,
client_kwargs={"scope": "openid profile email"},
# Set update_token to None to avoid unnecessary token updates
update_token=None,
)
def get_authorization_url(self, redirect_uri: str) -> str:
"""
Get HuggingFace OAuth authorization URL.
Args:
redirect_uri: Callback URL for OAuth flow
Returns:
Authorization URL string
"""
if not self.hf:
raise RuntimeError("OAuth not initialized. Call init_app() first.")
return self.hf.authorize_redirect(redirect_uri)
def fetch_token(self, **kwargs):
"""
Exchange authorization code for access token.
Returns:
Token dict with access_token, refresh_token, etc.
"""
if not self.hf:
raise RuntimeError("OAuth not initialized. Call init_app() first.")
return self.hf.authorize_access_token(**kwargs)
def fetch_userinfo(self, token):
"""
Fetch user information using access token.
Args:
token: Access token dict
Returns:
User info dict with sub, name, preferred_username, picture, email
"""
if not self.hf:
raise RuntimeError("OAuth not initialized. Call init_app() first.")
return self.hf.userinfo(token=token)
# Global auth service instance
auth_service = AuthService()