Files
GNX-mailEnterprise/venv/lib/python3.12/site-packages/allauth/socialaccount/providers/facebook/views.py
Iliyan Angelov c67067a2a4 Mail
2025-09-14 23:24:25 +03:00

130 lines
4.7 KiB
Python

import hashlib
import hmac
import logging
import requests
from datetime import timedelta
from django.utils import timezone
from allauth.socialaccount import app_settings
from allauth.socialaccount.adapter import get_adapter
from allauth.socialaccount.helpers import (
complete_social_login,
render_authentication_error,
)
from allauth.socialaccount.models import SocialLogin, SocialToken
from allauth.socialaccount.providers.oauth2.views import (
OAuth2Adapter,
OAuth2CallbackView,
OAuth2LoginView,
)
from .forms import FacebookConnectForm
from .provider import GRAPH_API_URL, GRAPH_API_VERSION, FacebookProvider
logger = logging.getLogger(__name__)
def compute_appsecret_proof(app, token):
# Generate an appsecret_proof parameter to secure the Graph API call
# see https://developers.facebook.com/docs/graph-api/securing-requests
msg = token.token.encode("utf-8")
key = app.secret.encode("utf-8")
appsecret_proof = hmac.new(key, msg, digestmod=hashlib.sha256).hexdigest()
return appsecret_proof
def fb_complete_login(request, app, token):
provider = app.get_provider(request)
resp = requests.get(
GRAPH_API_URL + "/me",
params={
"fields": ",".join(provider.get_fields()),
"access_token": token.token,
"appsecret_proof": compute_appsecret_proof(app, token),
},
)
resp.raise_for_status()
extra_data = resp.json()
login = provider.sociallogin_from_response(request, extra_data)
return login
class FacebookOAuth2Adapter(OAuth2Adapter):
provider_id = FacebookProvider.id
provider_default_auth_url = "https://www.facebook.com/{}/dialog/oauth".format(
GRAPH_API_VERSION
)
settings = app_settings.PROVIDERS.get(provider_id, {})
scope_delimiter = ","
authorize_url = settings.get("AUTHORIZE_URL", provider_default_auth_url)
access_token_url = GRAPH_API_URL + "/oauth/access_token"
access_token_method = "GET"
expires_in_key = "expires_in"
def complete_login(self, request, app, access_token, **kwargs):
return fb_complete_login(request, app, access_token)
oauth2_login = OAuth2LoginView.adapter_view(FacebookOAuth2Adapter)
oauth2_callback = OAuth2CallbackView.adapter_view(FacebookOAuth2Adapter)
def login_by_token(request):
ret = None
auth_exception = None
if request.method == "POST":
form = FacebookConnectForm(request.POST)
if form.is_valid():
try:
adapter = get_adapter()
provider = adapter.get_provider(request, FacebookProvider.id)
login_options = provider.get_fb_login_options(request)
app = provider.app
access_token = form.cleaned_data["access_token"]
expires_at = None
if login_options.get("auth_type") == "reauthenticate":
info = requests.get(
GRAPH_API_URL + "/oauth/access_token_info",
params={
"client_id": app.client_id,
"access_token": access_token,
},
).json()
nonce = provider.get_nonce(request, pop=True)
ok = nonce and nonce == info.get("auth_nonce")
else:
ok = True
if ok and provider.get_settings().get("EXCHANGE_TOKEN"):
resp = requests.get(
GRAPH_API_URL + "/oauth/access_token",
params={
"grant_type": "fb_exchange_token",
"client_id": app.client_id,
"client_secret": app.secret,
"fb_exchange_token": access_token,
},
).json()
access_token = resp["access_token"]
expires_in = resp.get("expires_in")
if expires_in:
expires_at = timezone.now() + timedelta(seconds=int(expires_in))
if ok:
token = SocialToken(
app=app, token=access_token, expires_at=expires_at
)
login = fb_complete_login(request, app, token)
login.token = token
login.state = SocialLogin.state_from_request(request)
ret = complete_social_login(request, login)
except requests.RequestException as e:
logger.exception("Error accessing FB user profile")
auth_exception = e
if not ret:
ret = render_authentication_error(
request, FacebookProvider.id, exception=auth_exception
)
return ret